Registering custom validators is done by calling the jQuery-based $.validator.register method. The register method takes a single JavaScript object literal argument. The parameter looks for four properties: selector, validate, show, and clear, of which the only selector is required.
The following example creates a custom validator for phone numbers in a Touch UI dialog. Note that show and clear methods are not necessary in this example as the validator would use the default AEM provided methods, however, they are included for reference.
aemTouchUIPhoneNumberValidator.js
/**
* Register phone number validation field looking for format "xxx-xxx-xxxx".
*
* The validator keys off of the ".field-phonenumber" selector. To use in Touch
* UI dialogs, add the class "field-phonenumber" to a textfield.
*
* <phonenumber
* jcr:primaryType="nt:unstructured"
* sling:resourceType="granite/ui/components/foundation/form/textfield"
* fieldLabel="Phone Number"
* fieldDescription="Format of "xxx-xxx-xxxx""
* class="field-phonenumber"
* name="./phonenumber"/>
*
* Touch UI dialog rendered HTML:
*
* <div class="coral-Form-fieldwrapper">
* <label class="coral-Form-fieldlabel">Phone Number</label>
* <input class="coral-Form-field coral-Textfield field-phonenumber" type="text" name="./phoneNumber" value="">
* </div>
*/
$.validator.register({
selector: '.field-phonenumber',
validate: function(el) {
var field,
value;
field = el.closest(".coral-Form-field");
value = el.val();
if (!/^\d{3}-\d{3}-\d{4}$/.test(value)) {
return Granite.I18n.get('The field must be a phone number in the format of "xxx-xxx-xxxx"');
}
},
show: function (el, message) {
var fieldErrorEl,
field,
error,
arrow;
fieldErrorEl = $("<span class='coral-Form-fielderror coral-Icon coral-Icon--alert coral-Icon--sizeS' data-init='quicktip' data-quicktip-type='error' />");
field = el.closest(".coral-Form-field");
field.attr("aria-invalid", "true")
.toggleClass("is-invalid", true);
field.nextAll(".coral-Form-fieldinfo")
.addClass("u-coral-screenReaderOnly");
error = field.nextAll(".coral-Form-fielderror");
if (error.length === 0) {
arrow = field.closest("form").hasClass("coral-Form--vertical") ? "right" : "top";
fieldErrorEl
.attr("data-quicktip-arrow", arrow)
.attr("data-quicktip-content", message)
.insertAfter(field);
} else {
error.data("quicktipContent", message);
}
},
clear: function (el) {
var field = el.closest(".coral-Form-field");
field.removeAttr("aria-invalid").removeClass("is-invalid");
field.nextAll(".coral-Form-fielderror").tooltip("hide").remove();
field.nextAll(".coral-Form-fieldinfo").removeClass("u-coral-screenReaderOnly");
}
});
The selector property ties the validator to the form elements on the page. The property accepts any jQuery selector such as a class ( .my-class-name), type ( INPUT) or attribute ( INPUT[type="text"]) selectors.
The validate property is the function that validates the form element's input. The function provides the form element as a jQuery object as the single available parameter. The field is treated as invalid if this function returns a string literal as the validation error message.
The show and clear properties are functions that update the UI when when the form element is determined to be invalid or valid respectively. Each function makes two parameters available, the form element as a jQuery object and the validation message.
The selector property is obviously required, otherwise the validator can never be called. However, the validate, show, and clear are optional. For example, if a form element is already being validated through an existing validator, you can update the UI behavior of the error message by registering a new validator with only show and clear functions. Order of registration is important; the last validator registered is the first validator used. View the Granite UI Validation documentation for further information. AEM's default validators are located at /libs/granite/ui/components/foundation/clientlibs/foundation/js/validation/validations.js.
The most obvious reason for providing custom show and clear functions is to validate a custom dialog component. For example, in the AEM Touch UI Validation Library, the two functions are used in the multifield validator as the field used is an HTML textbox to validate and it's not in the same HTML structure as the other HTML textboxes that the default AEM validator has already registered.
The benefit of using the provided jQuery.validator plugin is that it becomes trivial to create custom validation with a consistent UI provided by AEM out-of-the-box. As you write your custom validators, note that the jQuery.validator plugin attempts to mimic the default HTML5 validation and more importantly, note that hidden fields are not validated.
AEM provides a simple jQuery API to interact with form elements:
aemTouchUIValidation.js
var $input = $('.my-input-field'),
errorMessege = 'This field is required';
if ($input.willValidate()) {
$input.checkValidity(); // true
$input.validationMessage(); // ''
/* Set input field as invalid */
$input.setCustomValidity(errorMessage);
$input.checkValidity(); // false
$input.validationMessage(); // 'This field is required'
$input.updateErrorUI(); // displays red error icon
/* Set input field as valid */
$input.setCustomValidity(null);
$input.checkValidity(); // true
$input.validationMessage(); // ''
$input.updateErrorUI(); // removes red error icon
}
Using the principles described in this blog post, I've created the AEM Touch UI Validation Library to provide enhanced validation to Granite dialog components such as the multifield, browserpath, radiogroup, and autocomplete.
No comments:
Post a Comment
If you have any doubts or questions, please let us know.