如何通过 asp.net mvc 中的自定义 jQuery 验证复选框列表
How to validate a list of checkbox through custom jQuery in asp.net mvc
我有一个复选框列表,我想在客户端验证 jQuery 但失败了。我已经在我的项目中添加了 unobtrusive 和 jquery 验证插件。
型号代码为:
[Required]
public string name { get; set; }
[SkillValidation(ErrorMessage = "Select at least 3 skills")]
public List<CheckBox> skills { get; set; }
其他型号为:
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; }
}
说明 - SkillValidation() 是我创建的用于执行服务器端验证的自定义属性。
技能验证 class 代码是:
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);
}
}
说明:此代码将验证用户在服务器端至少选中 3 个复选框。我没有从 IClientValidatable 接口继承这个 class 因为我知道不可能从 MVC 方式(不显眼的方式)进行验证。
我的查看代码是:
@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")
说明:在视图中,我为名称创建了文本框,为使用 @Html.CheckBoxFor().
创建的技能创建了 6 个复选框
问题:问题是如果我删除 6 个复选框,那么客户端验证对名称文本框很有效。
如果我放置 6 个复选框并按下按钮,则只有服务器端验证适用于 name 和 checkboxe。
我希望客户端验证也适用于 6 个复选框,这样用户至少必须 select 3 个复选框。
我怎样才能实现它?
感谢
您无法使用 MVC 的客户端验证(通过实施 IClientValidatable
和使用 jquery.validation.unobtrusive.js)
来实现这一点。原因是客户端验证规则应用于表单控件,而您没有(并且cannot) 为你的 skills
属性 创建一个表单控件,它是一个集合,而不是一个简单的值类型。
您需要编写自己的脚本来验证选中复选框的数量(如果无效,请使用 @Html.ValidationMessageFor(model => model.skills)
生成的占位符
为了模仿 jquery 的 'lazy' 验证,首先处理 .submit()
事件,然后处理复选框的 .click()
事件。
修改您的第二个 <td>
元素以添加一个 id
属性来选择复选框(另请参阅下面的注释)
<td id="skills">
.... // your checkboxes
并添加以下脚本
var validateSkillsOnCheck = false; // for lazy validation
var requiredSkills = 3;
var skills = $('#skills input[type="checkbox"]');
var errorMessage = 'Select at least 3 skills';
var errorElement = $('span[data-valmsg-for="skills"]');
// function to validate the required number of skills
function validateSkills() {
var selectedSkills = skills.filter(':checked').length;
var isValid = selectedSkills > requiredSkills;
if (!isValid) {
errorElement.addClass('field-validation-error').removeClass('field-validation-valid').text(errorMessage);
} else {
errorElement.addClass('field-validation-valid').removeClass('field-validation-error').text('');
}
return (isValid);
}
$('form').submit(function () {
validateSkillsOnCheck = true;
if (!validateSkills()) {
return false; // prevent submit
}
});
$('#skills').on('click', 'input', function () {
if (validateSkillsOnCheck) {
validateSkills();
}
})
一些旁注。
- 表格用于表格数据,而不是布局并使用
<table>
element 不适合你的情况。
- 你的
@Html.LabelFor(model => model.skills)
不合适(你
skills
没有表单控件,因此点击它不会
将焦点放在任何东西上)。那应该只是一个 <span>@Html.DisplayNameFor(m =>m.skills)</span>
或类似的元素。
但是您应该为每个复选框创建标签。您的模型有 3 个属性,包括 Text
和 Value
并且不清楚它们之间的区别,无论如何,您永远不会将它们包含在视图中。我假设您至少要提交 Value
属性 以便您知道选择了哪些技能
<label>
@Html.CheckBoxFor(m =>m.skills[i].IsChecked)
<span>@Model.skills[i].Text</span>
</label>
@Html.HiddenFor(m =>m.skills[i].Value)
我有一个复选框列表,我想在客户端验证 jQuery 但失败了。我已经在我的项目中添加了 unobtrusive 和 jquery 验证插件。
型号代码为:
[Required]
public string name { get; set; }
[SkillValidation(ErrorMessage = "Select at least 3 skills")]
public List<CheckBox> skills { get; set; }
其他型号为:
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; }
}
说明 - SkillValidation() 是我创建的用于执行服务器端验证的自定义属性。
技能验证 class 代码是:
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);
}
}
说明:此代码将验证用户在服务器端至少选中 3 个复选框。我没有从 IClientValidatable 接口继承这个 class 因为我知道不可能从 MVC 方式(不显眼的方式)进行验证。
我的查看代码是:
@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")
说明:在视图中,我为名称创建了文本框,为使用 @Html.CheckBoxFor().
创建的技能创建了 6 个复选框问题:问题是如果我删除 6 个复选框,那么客户端验证对名称文本框很有效。
如果我放置 6 个复选框并按下按钮,则只有服务器端验证适用于 name 和 checkboxe。
我希望客户端验证也适用于 6 个复选框,这样用户至少必须 select 3 个复选框。
我怎样才能实现它?
感谢
您无法使用 MVC 的客户端验证(通过实施 IClientValidatable
和使用 jquery.validation.unobtrusive.js)
来实现这一点。原因是客户端验证规则应用于表单控件,而您没有(并且cannot) 为你的 skills
属性 创建一个表单控件,它是一个集合,而不是一个简单的值类型。
您需要编写自己的脚本来验证选中复选框的数量(如果无效,请使用 @Html.ValidationMessageFor(model => model.skills)
为了模仿 jquery 的 'lazy' 验证,首先处理 .submit()
事件,然后处理复选框的 .click()
事件。
修改您的第二个 <td>
元素以添加一个 id
属性来选择复选框(另请参阅下面的注释)
<td id="skills">
.... // your checkboxes
并添加以下脚本
var validateSkillsOnCheck = false; // for lazy validation
var requiredSkills = 3;
var skills = $('#skills input[type="checkbox"]');
var errorMessage = 'Select at least 3 skills';
var errorElement = $('span[data-valmsg-for="skills"]');
// function to validate the required number of skills
function validateSkills() {
var selectedSkills = skills.filter(':checked').length;
var isValid = selectedSkills > requiredSkills;
if (!isValid) {
errorElement.addClass('field-validation-error').removeClass('field-validation-valid').text(errorMessage);
} else {
errorElement.addClass('field-validation-valid').removeClass('field-validation-error').text('');
}
return (isValid);
}
$('form').submit(function () {
validateSkillsOnCheck = true;
if (!validateSkills()) {
return false; // prevent submit
}
});
$('#skills').on('click', 'input', function () {
if (validateSkillsOnCheck) {
validateSkills();
}
})
一些旁注。
- 表格用于表格数据,而不是布局并使用
<table>
element 不适合你的情况。 - 你的
@Html.LabelFor(model => model.skills)
不合适(你skills
没有表单控件,因此点击它不会 将焦点放在任何东西上)。那应该只是一个<span>@Html.DisplayNameFor(m =>m.skills)</span>
或类似的元素。 但是您应该为每个复选框创建标签。您的模型有 3 个属性,包括
Text
和Value
并且不清楚它们之间的区别,无论如何,您永远不会将它们包含在视图中。我假设您至少要提交Value
属性 以便您知道选择了哪些技能<label> @Html.CheckBoxFor(m =>m.skills[i].IsChecked) <span>@Model.skills[i].Text</span> </label> @Html.HiddenFor(m =>m.skills[i].Value)