Reputation: 361
I'm generating some controls with the help of a for-each loop. I would like to validate the textbox depend on the answer of the dropdown. For some questions, validator should be enabled if the selected item in dropdown is "yes" and for some questions validator should be enabled if the answer from the dropdown is "no". At the moment it fires for both because I don't how to control it as the controls are dynamically generated
View
@for (int a = 0; a < Model.ServiceQaVisits.Count(); a++)
{
if (Model.ServiceQaQuestions[a].sqqQuestionID == Model.ServiceQaVisits[a].sqvQuestionID)
{
<div>
@Html.DisplayTextFor(m => m.ServiceQaVisits[a].sqvQuestionID)
@Html.DisplayTextFor(m => m.ServiceQaQuestions[a].sqqQuestion)
@Html.HiddenFor(m => m.ServiceQaVisits[a].sqvQAID)
@if (Model.ServiceQaQuestions[a].sqqQuestionTypeID == 1)
{
@Html.TextBoxFor(m => m.ServiceQaVisits[a].sqvAnswer)
}
else if (Model.ServiceQaQuestions[a].sqqQuestionTypeID == 2)
{
List<string> lista = new List<string>() { "Yes", "No" };
@Html.DropDownListFor(m => m.ServiceQaVisits[a].sqvAnswer, new SelectList(lista), "Select Answer")
}
else
{
List<string> listb = new List<string>() { "Yes", "No", "N/A" };
@Html.DropDownListFor(m => m.ServiceQaVisits[a].sqvAnswer, new SelectList(listb), "Select Answer")
}
@if (Model.ServiceQaQuestions[a].sqqNegativeAnswer != null)
{
@Html.TextBoxFor(m => m.ServiceQaVisits[a].sqvComment)
@Html.ValidationMessageFor(m => m.ServiceQaVisits[a].sqvComment,"", new {@class = "text-danger"});
}
</div>
}
}
Model
[Required(ErrorMessage = "Please enter the reason")]
public string sqvComment { get; set; }
Any help is highly appreciated.
Upvotes: 0
Views: 2022
Reputation: 1810
There are two parts to the solution, as validation should happen both on server and on client.
On the server, you should use [CustomValidation]
attribute on your sqvComment
property. For example, your validation method can be
public static ValidationResult ValidateSqvComment(string value, ValidationContext context)
{
ValidationResult result = ValidationResult.Success;
MyModel model = context.ObjectInstance as MyModel;
if (model.sqvAnswer == "Yes" && String.IsNullOrEmpty(value))
{
result = new ValidationResult("sqvComment is required");
}
return result;
}
and decorate your property with
[CustomValidation(typeof(MyModel), nameof(MyModel.ValidateSqvComment))]
public string sqvComment { get; set; }
On the client things are more complicated. What MVC does, if you look at the generated source, is add special properties to the input
elements, that it then parses in client side to add the jQuery validation. in particular, it adds a data-val="true"
to enable validation, and then data-val-*=...
, depending on the type of validation. you need to dynamically add these attributes, and then call the parsing function to parse them. In your case, you need to add the data-val-required="sqvComment is required"
attribute to your sqvComment
field (through the htmlAttribute
argument of the Html.TextBoxFor()
method), and then set the value of data-val
to true
only if the answer to the drop-down is "Yes" (or whatever your logic is), using the onchange
event in client code. Then, you need to clear the validation that jQuery already picked up, and recreate it:
jqForm.removeData("unobtrusiveValidation");
jqForm.removeData("validator");
$.validator.unobtrusive.parse(formId);
where jqForm
is a jQuery object with your form, and formId
is a selector to the form.
Upvotes: 1