I have the following custom attribute that is used to validate if an array has had a value submitted:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
public sealed class RequiredArrayAttribute : RequiredAttribute, IClientValidatable
{
public RequiredArrayAttribute()
: base()
{
}
public override bool IsValid(object value)
{
var list = (IList)value;
if (list != null && list.Count > 0)
{
return true;
}
return false;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
string errorMessage = this.ErrorMessage;
// Get the specific error message if set, otherwise the default
if (string.IsNullOrEmpty(errorMessage) && metadata != null)
{
errorMessage = FormatErrorMessage(metadata.GetDisplayName());
}
var clientValidationRule = new ModelClientValidationRule()
{
ErrorMessage = errorMessage,
ValidationType = "requiredarray"
};
return new[] { clientValidationRule };
}
}
Applied to
[RequiredArray(ErrorMessage = "Please select at least one product")]
public IEnumerable<string> ProductIds { get; set; }
And the following js (included after jquery.js, unobtrusive-ajax.js, validate.js and validate.unobtrusive.js)
(function ($) {
$.validator.addMethod('requiredarray', function (value, element, params) {
var selector = 'input[name=' + $(element).attr('name') + ']:checked';
return $(selector).length > 0;
}, 'Clientside Should Not Postback');
$.validator.unobtrusive.adapters.addBool('requiredarray');
})(jQuery);
I have tried changing the addMethod
to just return false;
but this still does nothing (and no errors in my console)
I was wondering if anyone could spot anything I had done wrong with the above code. I have done a similar thing with an address attribute and it works just fine but for some reason I can't get this one to work?
Further to this the server side validation works.
Razor code for validation message
@Html.ValidationMessageFor(m => m.ProductIds)
Example html for rendered checkboxes:
<input type="checkbox" class="checkbox" name="ProductIds" value="EXAMPLEID1234" id="checkbox-1" checked="checked" />
<input type="checkbox" class="checkbox" name="ProductIds" value="EXAMPLEID1235" id="checkbox-2" checked="checked" />
EDIT
further to this I can now get the clientside validation to work using the following
$.validator.addClassRules('required-group', { 'requiredarray': true });
instead of the validator.unobtrusive.adapters.addBool
method in the above. I have also added the class required-group
to the checkbox
However, if I use this it doesn't add the proper MVC Error message, just the Clientside Should Not Postback
as set in the above code. I have tried adding the following attributes to the checkbox:
data-val="true" data-val-required="Please select at least one sample"
and also tried using data-val-requiredarray
but this makes no difference so does anyone know how to change the above clientside rules to make it use the MVC error message
So this was fixed with the following changes to the html:
<input type="checkbox" class="checkbox required-group" name="ProductIds" value="EXAMPLEID1234" id="checkbox-1" checked="checked" data-val-required="Please select at least one sample" />
<input type="checkbox" class="checkbox required-group" name="ProductIds" value="EXAMPLEID1235" id="checkbox-2" checked="checked" />
data-val-required
only needs to be on the first checkbox in the array. Then using the following jQuery:
(function ($) {
$.validator.addMethod('requiredarray', function (value, element, params) {
return $('input[name=' + $(element).attr('name') + ']:checked').length > 0;
}, 'Please select at least one');
$.validator.addClassRules('required-group', { 'requiredarray': true });
var errorMessage = $('.required-group').eq(0).data('val-requiredarray');
if (errorMessage && errorMessage !== "") {
$.validator.messages.requiredarray = errorMessage;
}
})(jQuery);
I have changed the addBool
to addClassRules
and then used $.validator.messages
to set the error message.
来源:https://stackoverflow.com/questions/24368156/custom-clientside-validation-for-required-at-least-one-in-array