I am trying to create a custom validation using IClientValidatable
I have 2 fields PhoneNumber and Mobile. I want the user to either or both. Only 1 is required but at least one must be provided.
I have managed to get to this so far
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
ValidationType = "required",
};
rule.ValidationParameters.Add("phone", "PhoneNumber");
rule.ValidationParameters.Add("mobile", "MobileNumber");
yield return rule;
}
This applies the validation to the outputted html elements
<input data-val="true" data-val-length="Mobile number must be a maximum length of 14." data-val-length-max="14" data-val-required="Landline or mobile phone number is needed." data-val-required-required="MobileNumber" id="MobileNumber" name="MobileNumber" type="text" value="">
<input data-val="true" data-val-length="Landline number must be a maximum length of 14." data-val-length-max="14" data-val-required="Landline or mobile phone number is needed." data-val-required-required="PhoneNumber" id="PhoneNumber" name="PhoneNumber" type="text" value="">
Now I know that’s not everything done. but if I try to hit the submit button the validation kicks in a shows 2 validation errors within my summary.
I am a little stuck on how to add the validator adapter.
So far….any I know its wrong but
jQuery.validator.unobtrusive.adapters.add('required',
[$("#PhoneNumber").val(), $("#MobileNumber").val()],
function(options) {
options.rules['required'] = options.params;
options.messages['required'] = options.message;
});
First, you will need to create your own validation attribute in a similar way than the Compare attribute.
In this attribute you will specify the other dependent property, and the error message will be formated to take into account the properties display names.
The attribute will look like this (I am not too proud about its name and default error message!):
So you can use it in your models as in:
With that code, the error messages “Please enter ‘Mobile’ or ‘Phone’.” and “Please enter ‘Phone’ or ‘Mobile’.” will be displayed when the server side validations fails. (You could set the same error message on both like “Please enter one…” )
In order to add the client side validation, you will need to create the adaptor for the unobtrusive validation. (Make sure you add it somewhere before the unobtrusive validation parses the document, otherwise you will need to manually parse it):
This is using a few of the utility functions defined in the unobtrusive validation library like:
Finally I have created a new validation rule. This is because although the required validation allows setting a filtering expression so the field is flagged only as valid when that expression is evaluated as true, see required validation, we need to apply a similar fix for onBlur validations than for the equalto rule.
The validation method is applying the said fix from the equalto validation, and then just calling the required rule with a dependent selector on the other related field, so the required validation returns false only when the field is blank and the dependent has not been filled.
If you don’t mind about that, as if you are validating only when the form is submitted, you could just write an adaptor that directly uses the required rule:
With all of this in place, your validation should work. If both are empty and you try to submit, error messages will be displayed for both fields. If you then enter something into one of them and tab out, both error messages should be removed.
You should also be able to adapt this to your needs, as you can modify the validation attribute, unobtrusive adaptor and validation rule.