客户端列表的MVC自定义validation

我试图编写一个自定义的validation器,在客户端工作,validation所有checkbox已勾选。

这是模型的声明:

[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; } } 

到目前为止好,工作服务器端。

对于客户端,我把它连接起来如下:

 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; }); 

我正在显示checkbox,如下所示:

 @{ var questionIndex = 0; } @foreach (var question in Model.DeclarationQuestions) { @Html.CheckBoxFor(model => Model.DeclarationQuestions[questionIndex].Answer, new { id = "DeclarationQuestions" + questionIndex}) questionIndex++; } 

然后使用这个显示validation消息:

 @Html.ValidationMessageFor(c => c.DeclarationQuestions) 

当我提交表单时,消息只显示在服务器上。 有没有办法让客户端的这个工作?

你不会得到客户端validation的原因是因为html助手为与属性相关的控件生成data-val-*属性。 jquery.validate.unobtrusive在表单parsing和使用规则时读取这些属性,在与该控件关联的ValidationMessageFor()生成的适当元素中显示错误消息(它通过匹配元素的id属性 – 错误消息在<span for="TheIdOfTheAssociatedControl" ...> )范围内生成。

您不(也不能)为属性DeclarationQuestions生成一个控件(仅用于DeclarationQuestions的每个项目的属性,所以没有任何东西可以匹配。

你可以通过包含你自己的错误信息占位符和拦截.submit事件来处理这个问题

HTML(添加CSS样式#conditions-error 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 } }); 

附注:你循环生成checkbox应该是

 for (int i = 0; i < Model.DeclarationQuestions.Count; i++) { @Html.CheckBoxFor(m => m.DeclarationQuestions[i].Answer, new { id = "DeclarationQuestions" + i}) }