MVC自定义验证对客户端列表

问题描述:

我想写一个自定义验证器上,用于验证所有复选框被选中的客户端工作。

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辅助生成数据-VAL - * 属性与属性相关联的控制。 jquery.validate.unobtrusive 读取当表单分析和使用规则的属性,显示通过生成相应的元素的错误消息ValidationMessageFor()与对照(有关它通过匹配了 ID做到这一点元素的属性 - 在跨度产生与&LT;跨度=TheIdOfTheAssociatedControl......方式&gt; )

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 $ C $控制C>所以没有什么可以匹配。

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样式#条件误差显示:无;

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