You can use the foundation-validation library for this. That way you can reuse the validation across all components in the project. Something as simple as adding a new property.
This has been tested on AEM 6.3/6.4 but should work with 6.2 as well.
Also this works on fields created using granite components as well as coral library. Minor changes will be required for Granite and Coral components as per requirement complexity.
Steps:
1.Create a generic clientlibs folder named touch-dialog-validation for the project with categories -> cq.authoring.dialog or any custom clientlib categories that you need. In case cq.authoring.dialog is used it is invoked by default but in case you are using custom clientlib categories then you need to include it in your template or component.
2.Include js file for writing validations.
3.Create a property named “validation” with the value registered with foundation.validation.validator in validations.js file. (In our case, the txt-validate property.)
4.Create “granite:data” node (nt:unstructured) under node where you need validation and add additional attributes as properties that might be needed for writing validation logic. (In our case, the pattern property.) Note: it need not always be validation property, we can use granite:class or granite:id as selectors. In this case the selector inside the validations.js will need to be changed accordingly.
If field within multifield, say textfield needs to be validated, same can be written and by simply using respective selector on field node validation can be achieved as shown below.
enter image description here
The code below validates a textfield to check for certain preset patterns. The preset patterns can be found at /libs/granite/ui/components/foundation/form/formbuilder/clientlibs/js/form-validation.js
(function($, window, document) {
/* Adapting window object to foundation-registry */
var registry = $(window).adaptTo("foundation-registry");
/*Validator for TextField - Any Custom logic can go inside validate function - starts */
registry.register("foundation.validation.validator", {
selector: "[data-validation=txt-validate]",
validate: function(el) {
var element = $(el);
var pattern = element.data('pattern');
var value = element.val();
if (value.length == 0) {
return "Please enter text";
} else {
patterns = {
phone: /([\+][0-9]{1,3}([ \.\-])?)?([\(]{1}[0-9]{3}[\)])?([0-9A-Z \.\-]{1,32})((x|ext|extension)?[0-9]{1,4}?)/,
email: /((([a-zA-Z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-zA-Z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?/,
url: /(https?|ftp):\/\/(((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?/,
// number: /-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?/,
number: /^\s*(\+|-)?((\d+(\.\d+)?)|(\.\d+))\s*$/,
dateISO: /\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/,
alpha: /[a-zA-Z]+/,
alphaNumeric: /\w+/,
integer: /-?\d+/,
systemKey: /^[-_a-z0-9]+$/i
}
/*
* Test pattern if set. Pattern can be a preset regex pattern name or
* a regular expression such as "^\\d+$".
*/
if (pattern) {
if (patterns[pattern]) {
error = !patterns[pattern].test(value);
} else {
error = !(new RegExp(pattern)).test(value);
}
if (error) {
return "The field must match the pattern: " + pattern;
}
}
}
}
});
})
($, window, document);
Example 1: Check for data not blank and contains URL.
CRX: enter image description here enter image description here
Output:
enter image description here enter image description here