问题描述
我正在尝试编写一个在客户端运行的自定义验证器,用于验证所有复选框是否已被勾选.
I'm trying to write a custom validator that works on the client side that validates that all checkboxes have been ticked.
这是关于模型的声明:
[DeclarationsAccepted(ErrorMessage = "You must tick all declarations")]
public IList<DeclarationQuestion> DeclarationQuestions { get; set; }
这是属性:
public class DeclarationsAccepted : ValidationAttribute, IClientValidatable
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var questions = value as IList<DeclarationQuestion>;
if (questions != null && questions.All(c => c.Answer))
{
return ValidationResult.Success;
}
return new ValidationResult("You must accepted all declarations to continue");
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var modelClientValidationRule = new ModelClientValidationRule
{
ValidationType = "declarationsaccepted",
ErrorMessage = FormatErrorMessage(metadata.DisplayName)
};
yield return modelClientValidationRule;
}
}
到目前为止一切顺利,在服务器端工作.
So far so good, works server side.
对于客户端,我将其连接如下:
For the client I'm wiring this up as follows:
jQuery.validator.addMethod('declarationsaccepted', function (value, element, params) {
//Implement logic here to check all boxes are ticked
console.log(value);
return false;
}, '');
jQuery.validator.unobtrusive.adapters.add('declarationsaccepted', {}, function (options) {
options.rules['declarationsaccepted'] = true;
options.messages['declarationsaccepted'] = options.message;
});
我正在显示这样的复选框:
I'm displaying the checkboxes like this:
@{ var questionIndex = 0; }
@foreach (var question in Model.DeclarationQuestions)
{
@Html.CheckBoxFor(model => Model.DeclarationQuestions[questionIndex].Answer, new { id = "DeclarationQuestions" + questionIndex})
questionIndex++;
}
然后使用此显示验证消息:
And then displaying the validation message using this:
@Html.ValidationMessageFor(c => c.DeclarationQuestions)
当我提交表单时,会显示消息,但仅在回发到服务器后才会显示.有没有办法让它在客户端工作?
When I submit the form the message is displayed but only after a post back to the server. Is there any way to get this to work on the client side?
推荐答案
你不会得到客户端验证的原因是因为 html 助手为与属性关联的控件生成 data-val-*
属性.jquery.validate.unobtrusive
在解析表单并使用规则时读取这些属性,在与该控件关联的 ValidationMessageFor()
生成的适当元素中显示错误消息(它这是通过匹配元素的 id
属性来实现的 - 错误消息是在带有 <span for="TheIdOfTheAssociatedControl" ...>
的范围内生成的.
The reason you will not get client side validation is because the html helpers generate data-val-*
attributes for controls associated with properties. jquery.validate.unobtrusive
reads those attributes when the form is parsed and using rules, displays an error message in the appropriate element generated by ValidationMessageFor()
associated with that control (it does this by matching up the id
attributes of the elements - the error message is generated in a span with <span for="TheIdOfTheAssociatedControl" ...>
).
您没有(并且不能)为属性 DeclarationQuestions
生成控件(仅用于 DeclarationQuestions
中每个项目的属性,因此没有任何可以匹配的内容.
You don't (and cant) generate a control for property DeclarationQuestions
(only for properties of each item in DeclarationQuestions
so there is nothing that can be matched up.
您可以通过包含自己的错误消息占位符并拦截 .submit
事件来处理此问题
You could handle this by including your own error message placeholder and intercepting the .submit
event
html(将 css 添加到样式 #conditions-error
为 display:none;
)
html (add css to style #conditions-error
as display:none;
)
<span id="delarations-error" class="field-validation-error">
<span>You must accept all declarations to continue.</span>
</span>
脚本
var declarationsError = $('#delarations-error');
$('form').submit(function() {
var isValid = $('.yourCheckBoxClass').not(':checked') == 0;
if(!isValid) {
declarationsError.show(); // display error message
return false; // prevent submit
}
});
$('.yourCheckBoxClass').change(function() {
if($(this).is(':checked')) {
declarationsError.hide(); // hide error message
}
});
旁注:生成复选框的循环应该是
Side note: You loop for generating the checkboxes should be
for (int i = 0; i < Model.DeclarationQuestions.Count; i++)
{
@Html.CheckBoxFor(m => m.DeclarationQuestions[i].Answer, new { id = "DeclarationQuestions" + i})
}
这篇关于客户端列表的 MVC 自定义验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!