I have a list of checkboxes that i want to validate on client side with jQuery but failing. I have already added unobtrusive and jquery validation plugin to my project.
The Model code is:
[Required]
public string name { get; set; }
[SkillValidation(ErrorMessage = "Select at least 3 skills")]
public List<CheckBox> skills { get; set; }
and other model is:
public class CheckBox
{
//Value of checkbox
public int Value { get; set; }
//description of checkbox
public string Text { get; set; }
//whether the checkbox is selected or not
public bool IsChecked { get; set; }
}
Explanation - SkillValidation() is the custom attribute which i have created to do server side validation.
The SkillValidation class code is:
public class SkillValidation : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
List<CheckBox> instance = value as List<CheckBox>;
int count = instance == null ? 0 : (from p in instance
where p.IsChecked == true
select p).Count();
if (count >= 3)
return ValidationResult.Success;
else
return new ValidationResult(ErrorMessage);
}
}
Explanation: This code will validate user to check at least 3 checkboxes on the server side. I did not inherited this class from IClientValidatable interface because i know it wont be possible to do validation from the MVC way (unobtrusive manner).
My View code is:
@model demo.MVC.Models.CB
@{
HtmlHelper.ClientValidationEnabled = true;
HtmlHelper.UnobtrusiveJavaScriptEnabled = true;
}
@using (Html.BeginForm())
{
<table>
<tr>
<td>
@Html.LabelFor(model => model.name)
@Html.EditorFor(model => model.name)
@Html.ValidationMessageFor(model => model.name)
</td>
<td>
@Html.LabelFor(model => model.skills)
@Html.CheckBoxFor(m => m.skills[0].IsChecked, new { id = "csharpSkill" }) C#
@Html.CheckBoxFor(m => m.skills[1].IsChecked, new { id = "aspSkill" }) ASP.NET
@Html.CheckBoxFor(m => m.skills[2].IsChecked, new { id = "jquerySkill" }) jQuery
@Html.CheckBoxFor(m => m.skills[3].IsChecked, new { id = "mvcSkill" }) ASP.NET MVC
@Html.CheckBoxFor(m => m.skills[4].IsChecked, new { id = "razorSkill" }) Razor
@Html.CheckBoxFor(m => m.skills[5].IsChecked, new { id = "htmlSkill" }) HTML
@Html.ValidationMessageFor(model => model.skills)
</td>
</tr>
<tr><td colspan="2"><button id="submitButton" type="submit">Submit</button></td></tr>
</table>
}
@Scripts.Render("~/jQuery")
@Scripts.Render("~/jQueryValidate")
@Scripts.Render("~/Unobtrusive")
Explanation: In the view i have created the text box for name and 6 checkboxes for the skills created with @Html.CheckBoxFor().
Problem: The problem is that If i remove the 6 checkboxes then client side validation works well for the name text box.
If i put 6 checkboxes and press the button then only the server side validation works for name and checkboxe.
I want client side validation to work for the 6 checkboxes too so that user has to select 3 checkboxes at least.
How can i achieve it ?
thanks
You cannot achieve that using MVC's client side validation (by implementing
IClientValidatable
and usingjquery.validation.unobtrusive.js)
. The reason is that client side validation rules are applied to form controls, and you do not (and cannot) create a form control for yourskills
property which is a collection, not a simple value type.You need to write your own scripts to validate the number of checked checkboxes (and if not valid, make use of the placeholder generated by
@Html.ValidationMessageFor(model => model.skills)
To mimic jquery's 'lazy' validation, initially handle the
.submit()
event, and there after, handle the.click()
event of the checkboxes.Modify your 2nd
<td>
element to add anid
attribute for selecting the checkboxes (see also notes below)and add the following scripts
A few side notes.
<table>
element is not appropriate in your case.@Html.LabelFor(model => model.skills)
is not appropriate (you do not have a form control forskills
so clicking on it does not set focus to anything). That should just be a<span>@Html.DisplayNameFor(m =>m.skills)</span>
or similar element.You should however be creating labels for each checkbox. Your model has 3 properties including
Text
andValue
and its not clear what the difference is between them, and in any case, you never include them in the view. I assume your will want to submit at least theValue
property so you know which skills have been selected