How to validate react hook form select field - react-hook-form

I am able to get value onChange after select any value in Countries but when I submit the form Error message displaying (but select has value)
<div className="form-group mb-3">
<label>Country</label>
<Controller
control={control}
name="country"
render={({
field: { onChange, onBlur, value, ref }
}) => (
<select className='form-control form-select'
onChange={(e) => setCountry(e.target.value)}
inputRef={register("country", { required: true })}
>
<option>Select Country</option>
{
Country.getAllCountries().map((item) => <option value={item.isoCode} key={item.isoCode}>{item.name}</option>)
}
</select>
)}
/>
{errors.country && <span className="error-text">Country is required</span>}
</div>
please see attached screen shot

This is the right way when your using Controller from react-hook-form:
<Controller
control={control}
name="country"
render={({field, fieldState: {invalid}}) => (
<>
<label>Country</label>
<select
{...field}
className='formcontrol form select'
onChange={({target:{value}) => {
changeCountry(value)
field.onChange(value)
}}>
<option>Select Country</option>
{Country.getAllCountries().map((item) => <option
value={item.isoCode}
key={item.isoCode}>{item.name}</option>)}
</select>
{invalid && <span className="error-text">Country is required</span>}
</>
}/>
If you don't have any special reasons do not desagregate field and use the values in fieldState provided by Controller they are related to the field rendered.

Related

getting empty list inside IActionResult on button submit - razor pages partial view

I am trying to pass a list of ids to IActionResult on button submit. The ids are coming from dropdown list selections. My view is a partial-view getting a model object. the problem is right now when i submit, the list is empty always.
I have read that we can not pass a list to controller! then what are the possible approaches, I am literally stuck on this for a day!
I have only pasted part of the code i felt is necessary to show,
please let me know if you want to see other code.
View.cshtml
<form method="post" asp-page-handler="UpdateComponent">
.
.
.
#{
var value1 = 0;
var value2 = 0;
var value3 =0;
}
<!-- asp-items="New plant SelectList"-->
<select class="form-control Shoplist News-plant-select_1 mt-2" data-search="true" asp-for="#value1">
<option value="">Bitte auswählen</option>
</select>
<br />
<!-- asp-items="New plant SelectList"-->
<select class="form-control Shoplist News-plant-select_2 mt-2" data-search="true" asp-for="#value2">
<option value="">Bitte auswählen</option>
</select>
<br />
<!-- asp-items="New plant SelectList"-->
<select class="form-control Shoplist News-plant-select_3 mt-2" data-search="true" asp-for="#value3">
<option value="">Bitte auswählen</option>
</select>
#{
Model.newsletterSubComponents.Add(new Models.NewsletterSubComponents() { NewPlantArticleId = value1 });
Model.newsletterSubComponents.Add(new Models.NewsletterSubComponents() { NewPlantArticleId = value2 });
Model.newsletterSubComponents.Add(new Models.NewsletterSubComponents() { NewPlantArticleId = value3 });
}
<input type="hidden" name="value1" value="#Model.newsletterSubComponents" asp-for="#Model.newsletterSubComponents"/>
.
.
.
<input type="submit" value="Speichern" class="btn btn-primary" />
</form>
controller
public IActionResult OnPostUpdateComponent(NewsletterComponents component, int? newsId, int? shortArticleId,
List<NewsletterSubComponents> newsletterSubComponents, int? test)
{
^
|
list empty
.
.
.
}
i populate dropdown lists using ajax
$.ajax(settings).done(function (data) {
$.each(data, function (index, element) {
$('.News-plant-select_1').append($("<option>").val(element.Id).text(element.NameGerman));
console.log(element.NameGerman);
$('.News-plant-select_2').append($("<option>").val(element.Id).text(element.NameGerman));
console.log(element.NameGerman);
});;
//remove spinner
$('.News-plant-select').removeClass("spinner-border");
});
If you want to receive ids, I think you can just use List< int > to receive it, also keep the parameter name the same as that in select element. I made an example based on your codes:
<form method="post" asp-page-handler="UpdateComponent">
#{
List<NewsletterSubComponents> newsletterSubComponents = new List<NewsletterSubComponents>
{
new NewsletterSubComponents{ NewPlantArticleId = 1, NewPlantArticleName = "AAA"},
new NewsletterSubComponents{ NewPlantArticleId = 2, NewPlantArticleName = "BBB"},
new NewsletterSubComponents{ NewPlantArticleId = 3, NewPlantArticleName = "CCC"}
};
var selectList = new SelectList(newsletterSubComponents, "NewPlantArticleId", "NewPlantArticleName");
}
<!-- asp-items="New plant SelectList"-->
<select name="newsletterSubComponentIds" class="form-control Shoplist News-plant-select_1 mt-2" data-search="true" asp-items="#selectList" >
<option value="">Bitte auswählen</option>
</select>
<br />
<!-- asp-items="New plant SelectList"-->
<select name="newsletterSubComponentIds" class="form-control Shoplist News-plant-select_2 mt-2" data-search="true" asp-items="#selectList">
<option value="">Bitte auswählen</option>
</select>
<br />
<!-- asp-items="New plant SelectList"-->
<select name="newsletterSubComponentIds" class="form-control Shoplist News-plant-select_3 mt-2" data-search="true" asp-items="#selectList">
<option value="">Bitte auswählen</option>
</select>
<input type="submit" value="Speichern" class="btn btn-primary" />
</form>
Result:

Getting all the values (checked and unchecked) from the dynamic checkbox in mvc

I'm adding a textbox and a corresponding checkbox to the view on click of a button. These checkbox will determine if the textbox value needs to be shown or hidden.
With the below code I've getting all the textbox fields, but for the checkbox I only get the checked values.
This is the view part
$('#btn-Add-Key-Name').click(function (e) {
i++;
e.preventDefault();
$(`<div class="row" id="rowid`+ i +`">
<div class= "col col-4" >
<section>
<label class="input">
<i class="icon-prepend fa fa-id-badge"></i>
<input type="text" name="KeyName" value="" placeholder="Key Name">
</label>
</section>
</div>
<div class="col col-2">
<label class="checkbox">
<input type="checkbox" name="IsKeyValid" value="true">
<i></i> Key
</label>
</div>
</div >`).appendTo($fields);
});
On the Controller
public JsonResult AddKeyToDB(string[] KeyName, IEnumerable<string> IsKeyValid)
{
}
//Is there a way to get the unchecked values as well for eg:
keyName = ["private", "public"] ,
IsKeyValid = ["false", "true"]
In your html you dont need to hard-code value of checkbox thats why you are only having checked values. So you need to make following change to your code. Just remove value="true" from input type checkbox.
<input type="checkbox" name="IsKeyValid" >

Dynamic name for react-final-form Field

I have 2 forms. When I choose an option on 1st form, the 2nd form is added to the page with the parameters retrieved from backend. Now how can I set the parameter names as react-final-form Field names?
I could not find a way to do this. Where to pass the parameter names?
<Form
onSubmit={onSubmit}
validate={validate}
React Final Form calls your onSubmit function with the values from all the fields in your form. It's totally up to you to transmit the values to your server.
If you're asking how to build the second form, you just add the fields you need to add. So, say you got back from the server that you needed three fields: [ 'name', 'startTime', 'endTime' ]. You'd just loop through that array and add the fields.
<Form onSubmit={onSubmit}>({handleSubmit}) => (
<form onSubmit={handleSubmit}>
{fieldsFromServer.map(fieldName => (
<div key={fieldName}>
<label>{fieldName}</label>
<Field name={fieldName} component="input"/>
</div>
))}
</form>
)}<Form>
Does that help? You don't have to "pass parameters to the form", you just add the Field components that you need.
Call the FinalForm like
<FinalFieldArrayForm onSubmit={this.handleSubmitTemplate} fieldsFromServer={parameters} />
and FinalForm is
import React from "react";
import ReactDOM from "react-dom";
import { Form, Field } from 'react-final-form'
import arrayMutators from 'final-form-arrays'
import { FieldArray } from 'react-final-form-arrays'
import "./styles.css";
const FinalForm = ({onSubmit, fieldsFromServer}) => (
<Form
onSubmit={onSubmit}
mutators={{
// potentially other mutators could be merged here
...arrayMutators
}}
render={({
handleSubmit,
form: {
mutators: { push, pop }
},
pristine,
form,
submitting,
values
}) => (
<form onSubmit={handleSubmit}>
<div className="buttons">
<button type="button" onClick={() => push('records', undefined)}>+</button>
<button type="button" onClick={() => pop('records')}>-</button>
<button type="button" onClick={form.reset} disabled={submitting || pristine}>Reset</button>
</div>
<FieldArray name="records">
{ ({fields}) => (
<div>
{fields.map( (name, index) => (
<div key={`${name}.${index}`}>
<label>{index + 1}</label>
{fieldsFromServer.map( param => <Field key={`${name}.${param}`} name={`${name}.${param}`} component="input" placeholder={`${name}.${param}`} /> )}
<button type="button" onClick={() => fields.remove(index)}>-</button>
<button type="button" onClick={() => fields.insert(index+1)}>+</button>
</div>
))}
</div>
)}
</FieldArray>
<div className="buttons">
<button type="submit" disabled={submitting || pristine}>Submit</button>
</div>
<pre>{JSON.stringify(values, 0, 2)}</pre>
</form>
)}
/>
)
const rootElement = document.getElementById("root");
ReactDOM.render(<FinalForm onSubmit={() => (<div/>)} fieldsFromServer={["firstName", "lastName"]} />, rootElement);

Select tag helper selected value not rendered in view

I need some help with my select tag helper.
I have an asp.net MVC View with a select 2 control as follows:
<div class="col-md-3">
<div class="form-group">
<label asp-for="NumberingType.Type" class="control-label" data-toggle="popover" data-placement="right" data-trigger="click" title="Field Help" data-content="Select the Numbering Scheme type that you want to create">Number Scheme Type *</label>
<select asp-for="NumberingType.TenantNumberingTypeId" asp-items="Model.NumberingType.NumberingTypeList" class="form-control select2">
<option></option>
</select>
<span asp-validation-for="NumberingType.TenantNumberingTypeId" class="text-danger"></span>
</div>
</div>
I am initialising the select2 as follows:
<script type="text/javascript">
$(document).ready(function () {
$(".select2").select2({
placeholder: "Select",
theme: 'bootstrap',
allowClear: true
});
});
</script>
I am loading the correct scripts:
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/js/select2.full.min.js"></script>
In my controller, I am populating the select 2 as follows:
public async Task<IActionResult> EditNumberScheme(int numberId)
{
var vm = new NumberingViewModel();
try
{
vm = await GetNumberingViewModel(numberId);
vm = UpdatedBaseViewModel<NumberingViewModel>(vm);
}
catch (Exception e)
{
await ErrorHandler.HandleException(e);
vm.MessageType = BaseViewModel.UserMessageType.Error;
}
return View(vm);
}
and
private async Task<NumberingViewModel> GetNumberingViewModel(int numberId)
{
var number = await DataGet.GetTenantNumberScheme(numberId);
NumberingViewModel model = new NumberingViewModel
{
Numbering = number
};
model.NumberingType = new TenantNumberingTypeModel();
model.NumberingType.NumberingTypeList = DataGet.GetTenantNumberingTypes().Result
.Select(x => new SelectListItem { Value = x.TenantNumberingTypeId.ToString(), Text = x.Type, Selected = (x.TenantNumberingTypeId == number.TenantNumberingTypeId) })
.ToList();
model.Owner = await DataGet.GetTenantOwner(UserInfo.Instance.Tenant.TenantId);
return model;
}
The select2 values are successfully loaded from the database and the selected value shows in the controller.
When placing a breakpoint at the select in the View, it is clear that the selected value is set as true in the NumberingTypeList.
Model.NumberingType.NumberTypeList = Count = 4
[1] = {Microsoft.AspNetCore.Mvc.Rendering.SelectListItem}
Disabled = false
Group = null
Selected = true
Text = "Credit Note"
Value = "2"
However the selected value is not rendered in the view.
<select class="form-control select2 select2-hidden-accessible" data-val="true" data-val-required="The TenantNumberingTypeId field is required." id="NumberingType_TenantNumberingTypeId" name="NumberingType.TenantNumberingTypeId" tabindex="-1" aria-hidden="true">
<option></option>
<option value="1">Invoice</option>
<option value="2">Credit Note</option>
<option value="3">Order</option>
<option value="4">Deposit</option>
</select>
Any help will be appreciated
Thanks
I managed to get this working by following this tutorial https://www.learnrazorpages.com/razor-pages/tag-helpers/select-tag-helper
It seems that the error is caused by the binding of the asp-for attribute. When I explicitly set the selected item in the controller as so:
model.NumberType = new TenantNumberingTypeModel();
model.NumberType.NumberSchemeList = DataGet.GetTenantNumberingTypes().Result
.Select(x => new SelectListItem { Value = x.TenantNumberingTypeId.ToString(), Text = x.Type })
.ToList();
model.NumberingType.TenantNumberingTypeId = number.TenantNumberingTypeId;
number being the object retrieved from the database
then it works correctly and the asp-items automatically selects the value that is represented by the asp-for attribute.
<select class="form-control select2 select2-hidden-accessible" data-val="true" data-val-required="Please select a type" id="NumberType_NumberTypeId" name="NumberType.NumberTypeId" tabindex="-1" aria-hidden="true">
<option></option>
<option value="1">Invoice</option>
<option selected="selected" value="2">Credit Note</option>
<option value="3">Order</option>
<option value="4">Deposit</option>
</select>
Hope this helps someone
That is the example of the visibility, you must use "select2.full.min.js".

Using uniForm and trying to disable input

I have a form that I have 2 different sets of formfields that are utilized depending on a select box value. The problem I am having is when I try to disable the irrelevant input fields, I the disabled attribute comes up as: disabled="" instead of disabled="disabled" here is the code I am using. It is a fairly complicated form so I will use the relevant fields so I can try to keep it as simple as possible for you all. If you think something is missing... please let me know if you need to see more.
<cfform id="entry-form" ACTION="index-10.cfm?Company" name="send" class="uniForm">
<div class="ctrlHolder"><label for="" style="display:none"><em>*</em>Builder or Individual</label>
<cfselect name="select1" id="select1">
<option value="" <cfif Individual is "">selected="selected"</cfif>>Who is this Case for? (choose one)</option>
<option value="0"<cfif Individual is 1>selected="selected"</cfif>>An Individual Home Owner</option>
<option value="1"<cfif Individual is not 1 and Individual is not "">selected="selected"</cfif>>A Builder</option>
</cfselect>
<p class="formHint">A selection is required</p>
</div>
<!--- this is for individual home owner. --->
<div class="hide" id="hide1">
<div class="ctrlHolder"><label for="" style="display:none"><em>*</em>First name</label>
<cfinput type="text"
name="FirstName"
id="FirstName"
data-default-value="Enter your first name"
size="35"
class="textInput required validateAlpha"
maxlength="50"
value="#FirstName#">
<p class="formHint">First Name is required</p>
</div>
</div>
<div class="hide" id="hide2">
<div class="ctrlHolder"><label for="" style="display:none"><em>*</em>Builder Name</label>
<cfinput type="text" id="builder"
name="BuilderName"
data-default-value="Type a builder's name"
size="35"
class="textInput required"
value="" />
<p class="formHint">Builder's name is required</p>
<cfinput id="builder_hidden" name="BuilderID" type="hidden" value="" />
<cfinput id="builder_hidden_plan" name="PlanID" type="hidden" value="" />
</div>
</div>
</cfform>
<script>
$(document).ready(function(){
$("#select1").change(function(){
if ($(this).val() == "1" ) {
$("#hide2").slideDown("fast"); //Slide Down Effect
$("#hide1").slideUp("fast");
$("#FirstName").prop("disabled", true);
$("#builder").prop("disabled", false);
} else if ($(this).val() == "0" ){
$("#hide1").slideDown("fast"); //Slide Down Effect
$("#hide2").slideUp("fast");
$("#FirstName").prop("disabled", false);
$("#builder").prop("disabled", true);
}
});
</script>
I am using:
jquery-1.9.1.js
jquery-ui-1.10.1.custom.js
uni-form-validation.jquery.js
I found the issue. The disabled property was being added. It was the required class that was keeping this from working. I added removeClass and addClass methods in order to correct this.
Please change the jQuery 'prop' to 'attr' & check the below script once it works fine.....
<script type="text/javascript">
$(document).ready(function(){
$("#select1").change(function(){
if ($(this).val() == "1" ){
$("#hide2").slideDown("fast"); //Slide Down Effect
$("#hide1").slideUp("fast");
$("#firstname").attr("disabled", "disabled");
$("#builder").attr("disabled", false);
}
else if ($(this).val() == "0" ){
$("#hide1").slideDown("fast"); //Slide Down Effect
$("#hide2").slideUp("fast");
$("#firstname").attr("disabled", false);
$("#builder").attr("disabled", "disabled");
}
});
});

Resources