********** Validation ********** Validation in Granite UI is achieved by using jQuery Validator plugin. jQuery Validator ================ jQuery.validator is a jQuery plugin that provides form validation, which is designed to replicate `HTML Forms Constraint Validation API `_. API === The plugin is exposed as ``jQuery.validator`` variable, exposing Validators interface (described as TypeScript): .. code-block:: ts interface Validators { /** * A flag to indicate that the validation process should continue to the next validator. */ CONTINUE: number; /** * A flag to indicate that the validation process should stop. This is default behavior. */ STOP: number; /** * Registers the given validator(s). * * Each validator will be iterated to check the validity of submittable elements, where the iteration stopped when the first matching validator says invalid. * The order of the registration is important, where the last one registered will be used first. * * @param validator One or more validator objects. */ register(...validator: Validator[]): void; /** * Returns true if all submittable elements under the given root element have no validity problems; false otherwise. * Fires invalid or valid event at submittable element when it is invalid or valid respectively. * * @param root The root element * * @return The validity */ isValid(root: JQuery): boolean; } interface Validator { /** * Only the element satisfying the selector will be validated using this validator. It will be passed to jQuery.fn.is. */ selector: string; /** * Only the element satisfying the selector will be validated using this validator. It will be passed to jQuery.fn.is. */ selector: (index: number, element: Element) => boolean; /** * The actual validation function. It must return a string of error message if the element fails. */ validate: (element: JQuery) => string; /** * The function to show the error. The function can return {@link Validators.CONTINUE} or {@link Validators.STOP}. */ show: (element: JQuery, message: string) => number; /** * The function to clear the error. The function can return {@link Validators.CONTINUE} or {@link Validators.STOP}. */ clear: (element: JQuery) => number; } It also exposes the following plugin methods to jQuery object (``jQuery.fn``): .. code-block:: ts interface ValidatorMethods { /** * Returns true if the element will be validated when the form is submitted; false otherwise. * * @see {@link http://www.w3.org/TR/html5/forms.html#dom-cva-willvalidate} */ willValidate: () => boolean; /** * Returns the error message that would be shown to the user if the element was to be checked for validity. * * @return The error message or an empty string * @see {@link http://www.w3.org/TR/html5/forms.html#dom-cva-validationmessage} */ validationMessage: () => string; /** * Returns true if the element's value has no validity problems; false otherwise. * Fires invalid or valid event at the element when it is invalid or valid respectively. * * @return The validity * @see {@link http://www.w3.org/TR/html5/forms.html#dom-cva-checkvalidity} */ checkValidity: () => boolean; /** * Sets a custom error, so that the element would fail to validate. * The given message is the message to be shown to the user when reporting the problem to the user. * If the argument is the empty string, clears the custom error. * * @param message The error message or empty string * @see {@link http://www.w3.org/TR/html5/forms.html#dom-cva-setcustomvalidity} */ setCustomValidity: (message: string) => void; /** * Shows error UI if the element is invalid; hide the UI otherwise. */ updateErrorUI: () => void; } Mechanism ========= Applicable Element ------------------ The plugin is only validating the element satisfying the following selectors: * input:not([readonly],[disabled],[type=hidden],[type=reset],[type=button]) * select * textarea:not([readonly]) * button[type=submit] * [role=checkbox]:not([aria-disabled=true]) * [role=radio]:not([aria-disabled=true]) * [role=combobox]:not([aria-disabled=true]) * [role=listbox]:not([aria-disabled=true]) * [role=radiogroup]:not([aria-disabled=true]) * [role=tree]:not([aria-disabled=true]) * [role=slider]:not([aria-disabled=true]) * [role=spinbutton]:not([aria-disabled=true]) * [role=textbox]:not([aria-disabled=true],[aria-readonly=true]) The selectors are specifically designed to enforce form semantic and accessibility (using `WAI-ARIA `_). Form Submission --------------- It will `capture `_ the form ``submit`` event to cancel and stop propagating the event when the form is invalid. If there is `novalidate `_ attribute, the validation process is skipped. During the event capturing of ``submit`` event, it will perform the following pseudo-code: .. code-block:: javascript function validateForm(form, submitEvent) { var controls = getApplicableElements(form); var invalids = []; var unhandleds = []; controls.forEach(function(field) { if (!validateField(field)) { invalids.push(field); } }); if (invalids.length === 0) { // The form is valid return; } invalids.forEach(function(field) { var e = createEvent("invalid"); field.trigger(e); if (!e.isDefaultPrevented()) { unhandleds.push(field); } }); if (unhandleds.length === 0) { return; } unhandleds.forEach(function(field) { showErrorUI(field); }); submitEvent.stopPropagation(); submitEvent.preventDefault(); } Validator --------- The plugin itself is not performing the actual validation. Rather a validator can be registered using ``jQuery.validator.register``. It doesn’t provide any pre-registered validator. Example ^^^^^^^ We need a validator to check the max length of a textfield (e.g. ````, ``