MVC Custom Validation para la lista en el lado del cliente

Intento escribir un validador personalizado que funcione en el lado del cliente que valide que todas las casillas de verificación hayan sido marcadas.

Aquí está la statement sobre el modelo:

[DeclarationsAccepted(ErrorMessage = "You must tick all declarations")] public IList DeclarationQuestions { get; set; } 

Y aquí está el atributo:

 public class DeclarationsAccepted : ValidationAttribute, IClientValidatable { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { var questions = value as IList; if (questions != null && questions.All(c => c.Answer)) { return ValidationResult.Success; } return new ValidationResult("You must accepted all declarations to continue"); } public IEnumerable GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { var modelClientValidationRule = new ModelClientValidationRule { ValidationType = "declarationsaccepted", ErrorMessage = FormatErrorMessage(metadata.DisplayName) }; yield return modelClientValidationRule; } } 

Hasta ahora todo bien, funciona del lado del servidor.

Para el cliente estoy conectando esto de la siguiente manera:

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

Estoy mostrando las casillas de verificación de esta manera:

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

Y luego mostrar el mensaje de validación usando esto:

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

Cuando envío el formulario, se muestra el mensaje, pero solo después de una publicación en el servidor. ¿Hay alguna forma de hacer que esto funcione en el lado del cliente?

La razón por la que no obtendrá la validación del lado del cliente es porque los helpers html generan atributos data-val-* para los controles asociados con las propiedades. jquery.validate.unobtrusive lee esos atributos cuando se analiza el formulario y usa reglas, muestra un mensaje de error en el elemento apropiado generado por ValidationMessageFor() asociado con ese control (lo hace haciendo coincidir los atributos de id de los elementos – el error el mensaje se genera en un lapso con ).

Usted no (y no puede) generar un control para la propiedad DeclarationQuestions (solo para las propiedades de cada elemento en DeclarationQuestions modo que no hay nada que pueda emparejarse).

Puede manejar esto incluyendo su marcador de posición de mensaje de error e interceptando el evento .submit

html (agregue css a style #conditions-error como display:none; )

  You must accept all declarations to continue.  

Guión

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

Nota al margen: el bucle para generar las casillas de verificación debe ser

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