1

I am using ASP.NET MVC 5 and on the client side want to use JQuery unobtrusive validation.

Following is my model:

 public class CompanyModel { public CompanyModel() { Employees = new List<EmployeeModel>(); } public int CompanyId{ get; set; } public List<EmployeeModel> Employees { get; set; } } public class EmployeeModel { public EmployeeModel() { Values = new List<string>(); } public string Id { get; set; } public string Name { get; set; } [RequiredIf("IsRequired", true, "Atleast one value is required")] public List<string> Values { get; set; } public bool IsRequired { get; set; } } 

I was able to implement the RequiredIf custom attribute successfully on the server side. But I'm struggling to get the client side validation going...

In the view I loop through the employees list and the values collection is bound

@for (var index = 0; index < Model.Employees.Count; index++) { /// some other code @for (int i = 0; i < Model.employees[index].Values.Count; i++) { @Html.TextBoxFor(m => m.Employees[index].Values[i], new {@autocomplete = "false" }) } } 

The IsRequired property is a hidden field:

@Html.HiddenFor(m => m.Employees[index].IsRequired) 

The following is the code I have so far for the GetClientValidationRules method.

 public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { var rule = new ModelClientValidationRule { ErrorMessage = ErrorMessage, ValidationType = "requiredif" }; rule.ValidationParameters["dependentproperty"] = (context as ViewContext).ViewData.TemplateInfo.GetFullHtmlFieldId(DependentProperty); rule.ValidationParameters["dependentpropertyvalue"] = DependentPropertyValue.ToString().ToLower(); yield return rule; } 

I don't see the validation html (data-val-*) attributes added to the values in the HTML markup. And I don't expect them too as I think I am missing something. How do I get all the elements of the values collection populated with the data-val-requiredif attributes in html.

Any ideas?

FYI: the dependentpropertyId in html is populated like so CompanyModel.Employees_0_IsRequired for Employee[0].

7
  • 1
    You cannot get jquery client side validation for a property which is a collection since your cannot generate a form control for a collection (only for properties of the collection). You would need to write you own client side scripts in order to display you own client side message.
    – user3559349
    CommentedMar 7, 2016 at 21:54
  • ok, thanks I see. @StephenMuecke do you then suggest doing something similar to what the accepted answer suggests here. stackoverflow.com/questions/5662589/… or adding the data-val and data-val-requiredif attributes to html manually and then write a jquery validate adapter?CommentedMar 11, 2016 at 16:54
  • @Sparky(stackoverflow.com/users/594235/sparky) same question to you too?CommentedMar 11, 2016 at 17:02
  • I don't know a lot about ASP or its Unobtrusive plugin, but as far as jQuery Validate, no special methods are required to validate a group of checkboxes or radio buttons. See: jsfiddle.net/af68u6z3
    – Sparky
    CommentedMar 11, 2016 at 17:20
  • I also cannot see your rendered HTML, so I have no idea what a List<string> is supposed to be. However, using jQuery Validate, you can only validate textarea, select , and various types of input elements; nothing else.
    – Sparky
    CommentedMar 11, 2016 at 17:21

2 Answers 2

2

There is little point including the GetClientValidationRules() method in your validation attribute, because its purpose is to add the data-val-* attributes to the form control generated for that property, ad you don't generate an input for property Values (and if you did, binding would fail). One way to solve this is to handle the forms .submit() event, check if at least one item in the collection has a value, and if not cancel the submit and display the error.

Modify your view to include the validation message place holder and add a class name to the inputs for selection

@for (var index = 0; index < Model.Employees.Count; index++) { .... <div class="value-group"> // necessary for relative selectors @for (int i = 0; i < Model.employees[index].Values.Count; i++) { @Html.TextBoxFor(m => m.Employees[index].Values[i], new { @class="value", autocomplete = "false" }) } @Html.ValidationMessageFor(m => m.Employees[index].Values) </div> } 

And include the following script

$('form').submit(function() { // use an id selector if you have added one to the form var isValid = true; var groups = $('.value-group'); $.each(groups, function(index, item) { var group = $(this); var inputs = group.find('.value'); if (inputs.filter(function () { return $(this).val().length > 0; }).length == 0) { isValid = false; group.find('span:last').append($('<span></span>').text('At least one value is required')).addClass('field-validation-error').removeClass('field-validation-valid'); } }); return isValid; }); 

You may also want to add another script to handle the change event of each input to remove the associated error message if any of the inputs in the group now have a value

0
    0

    The Required validation only ensures that the property has a value. In the case of something like a List<string> that means only that it's not null. An empty list is still a list, so it passes validation fine. You're using RequiredIf, actually, and haven't provide the implementation of that custom attribute, but I would assume it leans on the base Required attribute, since pretty much every implementation I've seen does.

    Long and short, you'll either need to modify your RequiredIf implementation to consider the content of lists and other enumerable properties, or you'll need to add some manual validation to check that the list actually has at least one item.

    1
    • Yeah I check the count on the list to make sure Count > 0, and that's server side. I' can't get the client side working.CommentedMar 7, 2016 at 17:43

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.