Form Validation
Importing the Validation class queries the current page for <form> elements
and disables the default browser constraint validation
by adding a novalidate attribute to that element.
The default behavior is to validate each field when their value is updated,
and validate the entire form when it is submitted. This can be changed to only
validate on form submission by setting onlyOnSubmit to true on the
instance.
Once a field is marked invalid, it will always re-validate when its value is
changed regardless of the onlyOnSubmit value.
requiredfields are tested for blank first. If this check is passed, the field will then test for custom rules if present. If there are no custom rules, some fields are also tested further based on theirtypeattribute value. These are described below.
Required Fields
Usually, the majority of fields in a form need validation. To make setup
easier, instances of the Validation class have a default reqAll
value of true. This marks all fields that meet the following criteria
required and needing validation:
- Have a
nameattribute. - Not
disabled.
Indivudual fields can then be excluded from validation as described below.
This functionality can be inverted by setting reqAll to false,
and manually giving your required fields a required
attribute.
<div class="form-group">
<label for="text">Text</label>
<input required id="text" type="text" name="text">
</div>
<input> type attribute values of checkbox and radio only need one option to have the
required attribute, however, it is recommended to add it to all options for
consistency. More information on checkbox and radio fields can be found below.
Required Indicator
A <span> tag with class of required__indicator containing an asterisk(*)
character will be inserted beforeend
of a required field's <label> element.
This indicator will be inserted to the <legend> element of checkbox and
radio <input> types if present as described below.
The indicator can be disabled or customized as described in Form Options.
Markup
The Validation class requires the following for each required field:
- All form fields to be wrapped in an element with the
form-groupclass. - Do NOT nest the required field in a
<label>element. - Unique, matching values of the required field's
idand its<label>'sforattribute. - A unique
nameattribute on the required field.checkboxandradio<input>types should share the same uniquenameattribute.
When a field fails validation the wrapper
.form-groupelement will receive aninvalidCSS class. Use this to write your own CSS to indicate an invalid state.
<div class="form-group">
<label for="text">Text</label>
<input id="text" type="text" name="text">
</div>
Checkbox and Radio Fields
- Wrap all options in a
<fieldset>element and add theform-groupclass to it instead of the individual options. - The
<legend>tag may be used to give the option set a heading. - Each
checkboxorradio<input>type should be wrapped in aform-group__itemclass. This class is not used programattically, and is only used for styling.
<fieldset class="form-group">
<legend>Check Group</legend>
<span class="form-group__item">
<input id="checkbox-1" type="checkbox" name="checks">
<label for="checkbox-1">Checkbox 1</label>
</span>
<span class="form-group__item">
<input id="checkbox-2" type="checkbox" name="checks">
<label for="checkbox-2">Checkbox 2</label>
</span>
</fieldset>
Select Fields
Required <select> elements should contain an <option> with the selected
attribute and an empty value attribute. If not present the element will pass
validation even while being required.
<div class="form-group">
<label for="select">Select</label>
<select id="select" name="select">
<option selected value="">Choose an Item</option>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
</div>
Password Fields
When an <input> element with a type attribute of password is detected on the
page, a required Password Confirm field will auto generate after its parent
.form-group wrapper.
The markup for this field is a duplicate of the original input's parent
.form-group wrapper. The id and name attributes of the <input> element,
and the for attribute of the <label> element will have their values set to
password-confirm.
This functionality can be disabled by settting passConfirm to false.
A Password field with the markup of
<div class="form-group">
<label for="password">Password</label>
<input id="password" type="password" name="password">
</div>
will generate a Password Confirm field with the markup of
<div class="form-group">
<label for="password-confirm">Password Confirm<span class="required__indicator">*</span></label>
<input id="password-confirm" type="password" name="password-confirm">
</div>
The Password field is tested that it matches its corresponding Password Confirm field when the Password Confirm field contains a non-blank value.
The Password Confirm field is always tested that it matches its corresponding Password field.
Custom Form Controls
Custom form controls can be validated by informing the ValidationField class what you want to check against as the value for your control. You can determine validity based on:
- Existence of an element.
- TextContent of an element.
- Existence of an attribute.
- Value of an attribute.
To validate a custom form control, add a data-validation attribute to an
element of the control. The value should be a single quoted JSON object with
valueSrc as a property.
The element that the
data-validationattribute is added to MUST have a uniqueidandnameattribute. Having an associatedlabel/legendtag with aforattribute is optional, but recommended.
The value of the property should be an array with up to three items.
valueSrc[0]: A CSS selector to target the element to reference for value.
valueSrc[1]: The keyword attribute, attributeValue, exists, or
textContent.
valueSrc[2]: If using attribute or attributeValue, the attribute to
reference. If using exists, a CSS selector relative to valueSrc[0] as the
parent.
valueSrc can be combined with pattern and patternMessage
field options to check for specific values and output custom error messages.
See the examples below.
Existence of an Element
Determine validity based on whether an element exists or not.
Valid if... the target element exists.
The following example checks for the presence of in image element that is a child of the element with an id of 'custom-control'.
<div class="form-group">
<label for="custom-control">Custom Form Control</label>
<div data-validation='{"valueSrc": ["#custom-control", "exists", "img"]}' id="custom-control" name="custom_control"></div>
</div>
The third item in the
valueSrcarray can be any valid CSS selector string thatquerySelectorcan parse. e.x.:scope > img
TextContent of an Element
Use the target element's textContent
to determine validity. Useful when using contenteditable.
Valid if... the target element's textContent property is a non-empty string.
The following example checks if the element with an id of 'custom-control' has
a non-empty string textContent
property.
<div class="form-group">
<label for="custom-control">Custom Form Control</label>
<div data-validation='{"valueSrc": ["#custom-control", "textContent"]}' id="custom-control" name="custom_control" contenteditable></div>
</div>
Existence of an Attribute
Use the target element's specified attribute existence to determine validity.
Valid if... the target element's specified attribute exists.
The following example checks if the element with an id of 'custom-control' has
a title attribute.
<div class="form-group">
<label for="custom-control">Custom Form Control</label>
<div data-validation='{"valueSrc": ["#custom-control", "attribute", "title"]}' id="custom-control" name="custom_control"></div>
</div>
The value of a boolean attribute will evaluate as
falseand invalid unless it is a non-empty string. When using this option, the attribute must use thechecked="checked"(true, valid) andchecked=""(false, invalid) form and notchecked.checkedwill evaluate as false and invalid whether present or not.
Value of an Attribute
Use the target element's specified attribute value to determine validity.
Valid if... the value of the target's specified attribute is a non-empty string.
The following example checks if the element with an id of 'custom-control' has
a title attribute with a non-empty string value.
<div class="form-group">
<label for="custom-control">Custom Form Control</label>
<div data-validation='{"valueSrc": ["#custom-control", "attributeValue", "title"]}' id="custom-control" name="custom_control"></div>
</div>
The value of a boolean attribute will evaluate as
falseand invalid unless it is a non-empty string. When using this option, the attribute must use thechecked="checked"(true, valid) andchecked=""(false, invalid) syntax. If you need to check a boolean attribute useattribute.
Form Options
- invalidClass
- messageClass
- onlyOnSubmit
- onSuccess
- passConfirm
- reqAll
- reqIndicator
- reqIndicators
- reqIndicatorClass
- valFieldsOn
Default instance options can be overwritten by adding a single quoted
data-validation attribute on the <form> being validated. Its value must be
a properly formatted JSON object.
<form data-validation='{"onlyOnSubmit": true, "reqIndicator": "❗️"}'>
<div class="form-group">
<label for="text">Text</label>
<input id="text" type="text" name="text">
</div>
<div class="form-group">
<button type="submit">Submit</button>
</div>
</form>
invalidClass
Default: invalid
The class assigned to the parent <div class="form-group" /> wrapper of the
invalid field.
messageClass
Default: invalid__message
The class assigned output message of the invalid field.
onlyOnSubmit
Default: false
Only validate the form on submission. A setting of true will disable
individual field validation. Regardless of this setting fields will always
validate on the valFieldsOn value while they are invalid.
onSuccess
Default: null
Run a script when the form is submited and all fields pass validation. A non truthy value will cancel the form's default action.
<form data-validation='{"onSuccess": "save()"}'>...</form>
passConfirm
Default: true
Automatically create a confirm password field. The markup from the user created
field with a type="password" attribute will be duplicated and modifed, then
inserted after the original field.
<form data-validation='{"passConfirm": true}'>...</form>
reqAll
Default: true
Automatically add a required attribute to all <input>, <select>, and
<textarea> tags in the <form>. This allows you to skip marking individual
fields as required in your markup.
Individual fields can be excluded from validation by adding a
data-validationattribute to a field that's value is a JSON object with anoptionalproperty value set totrue.
<div class="form-group">
<label for="not-required">Not Required</label>
<input data-validation='{"optional": true}' id="not-required" type="text" name="not_required">
</div>
reqIndicator
Default: *
The string to render after the label text to indicate to the user that the field is required.
reqIndicators
Default: true
Enable the output of reqIndicator strings.
If set to false, you can target all field labels with the CSS selector below
to apply a custom style.
.form-group:has([required])
:where(label:has(:not(.form-group__item)), legend) {
/* Your styles here. */
}
reqIndicatorClass
Default: required__indicator
The class assigned to the <span> wrapper of the outputted reqIndicator.
valFieldsOn
Default: input
The event that triggeers individual field validation. Value can be any
JavaScript event, but it is recommended to try
blur,
change,
or input.
Individual field validation can be disable by setting
onlyOnSubmitto true.
Field Options
Individual fields can be passed options to customize their behavior by adding a
single quoted data-validation attribute to a field. Its value must be a
properly formatted JSON object with the properties and values below.
<div class="form-group">
<label for="custom">Custom Regex</label>
<input data-validation='{"optional": true,
"pattern": "^[0-9]*$",
"patternMessage": "This field must only contain numbers."
}'
id="custom" type="text" inputmode="numeric" name="custom">
</div>
optional
Default: false
Fields with the optional property set to true will pass vaidation when
blank. They still will be processed for validation when they contain a value
based on the input type attribute, or if a user pattern is specified.
pattern
Default: null
A regular expression to test the field's value against. This string is also
copied and added to the field as a native pattern
attribute. It is recommended to also provide an error message to display when
the value does not match pattern by providing a patternMessage.
The pattern is checked when input is present. A required field will always first test for blank, then for the provided pattern.
patternMessage
Default: null
An error message to display when the field fails the custom validation test
provided by pattern.
If not provided with
patternthe field will be marked as invalid, but no message will output when the pattern does not match.
valueSrc
Default: null
Used to validate custom form controls. See here for more information.