468 lines
16 KiB
Markdown
468 lines
16 KiB
Markdown
# Demo
|
|
|
|
A demo of the form validation class can be found [here](https://demos.danremollino.dev/form-validation/).
|
|
|
|
# Documentation
|
|
|
|
Importing the `Validation` class queries the current page for `<form>` elements
|
|
and disables the default browser [constraint validation](https://developer.mozilla.org/en-US/docs/Web/HTML/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`](#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`](#onlyOnSubmit) value.
|
|
|
|
> `required` fields are tested for blank first. If this check is passed, the
|
|
field will then test for [custom rules](#custom-validation) if present. If
|
|
there are no custom rules, some fields are also tested further based on their
|
|
`type` attribute value. These are described [below](#markup).
|
|
|
|
## 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`](#reqall)
|
|
value of `true`. This marks all fields that meet the following criteria
|
|
required and needing validation:
|
|
|
|
* Have a `name` attribute.
|
|
* Not [`disabled`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/disabled).
|
|
|
|
Indivudual fields can then be excluded from validation as described [below](#reqall).
|
|
|
|
This functionality can be inverted by setting [`reqAll`](#reqall) to `false`,
|
|
and manually giving your required fields a [`required`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/required)
|
|
attribute.
|
|
|
|
```html
|
|
<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](#checkbox-and-radio-fields).
|
|
|
|
### Required Indicator
|
|
|
|
A `<span>` tag with class of `required__indicator` containing an asterisk(*)
|
|
character will be inserted [`beforeend`](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML#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](#checkbox-and-radio-fields).
|
|
|
|
The indicator can be disabled or customized as described in [Form Options](#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-group` class.
|
|
- Do **NOT** nest the required field in a `<label>` element.
|
|
- Unique, matching values of the required field's `id` and its `<label>`'s `for`
|
|
attribute.
|
|
- A unique `name` attribute on the required field. `checkbox` and `radio`
|
|
`<input>` types should share the same unique `name` attribute.
|
|
|
|
> When a field fails validation the wrapper `.form-group` element will receive
|
|
an `invalid` CSS class. Use this to write your own CSS to indicate an invalid
|
|
state.
|
|
|
|
```html
|
|
<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 the `form-group` class to
|
|
it instead of the individual options.
|
|
- The `<legend>` tag may be used to give the option set a heading.
|
|
- Each `checkbox` or `radio` `<input>` type should be wrapped in a
|
|
`form-group__item` class. This class is not used programattically, and is only
|
|
used for styling.
|
|
|
|
```html
|
|
<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.
|
|
|
|
```html
|
|
<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`](#passConfirm) to `false`.
|
|
|
|
A *Password* field with the markup of
|
|
|
|
```html
|
|
<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
|
|
|
|
```html
|
|
<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.
|
|
<br><br>
|
|
The *Password Confirm* field is always tested that it matches its corresponding
|
|
*Password* field.
|
|
|
|
## Custom Form Controls
|
|
|
|
[Custom form controls](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Forms/How_to_build_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:
|
|
|
|
1. [Existence of an element.](#existence-of-an-element)
|
|
2. [TextContent of an element.](#textcontent-of-an-element)
|
|
3. [Existence of an attribute.](#existence-of-an-attribute)
|
|
4. [Value 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-validation` attribute is added to **MUST** have a
|
|
unique `id` and `name` attribute. Having an associated `label`/`legend` tag
|
|
with a `for` attribute 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.<br>
|
|
`valueSrc[1]:` The keyword `attribute`, `attributeValue`, `exists`, or
|
|
`textContent`.<br>
|
|
`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`](#pattern) and [`patternMessage`](#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'.
|
|
|
|
```html
|
|
<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 `valueSrc` array can be any valid CSS selector string
|
|
that [`querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)
|
|
can parse. e.x. `:scope > img`
|
|
|
|
### TextContent of an Element
|
|
|
|
Use the target element's [`textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent)
|
|
to determine validity. Useful when using [`contenteditable`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/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`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent)
|
|
property.
|
|
|
|
```html
|
|
<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.
|
|
|
|
```html
|
|
<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](https://developer.mozilla.org/en-US/docs/Glossary/Boolean/HTML)
|
|
will evaluate as `false` and invalid unless it is a non-empty string. When
|
|
using this option, the attribute must use the `checked="checked"` (true, valid)
|
|
and `checked=""` (false, invalid) form and not `checked`. `checked` will
|
|
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.
|
|
|
|
```html
|
|
<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](https://developer.mozilla.org/en-US/docs/Glossary/Boolean/HTML)
|
|
will evaluate as `false` and invalid unless it is a non-empty string. When
|
|
using this option, the attribute must use the `checked="checked"` (true, valid)
|
|
and `checked=""` (false, invalid) syntax. If you need to check a boolean
|
|
attribute use [`attribute`](#existence-of-an-attribute).
|
|
|
|
## Form Options
|
|
|
|
* [invalidClass](#invalidclass)
|
|
* [messageClass](#messageclass)
|
|
* [onlyOnSubmit](#onlyonsubmit)
|
|
* [onSuccess](#onsuccess)
|
|
* [passConfirm](#passconfirm)
|
|
* [reqAll](#reqall)
|
|
* [reqIndicator](#reqindicator)
|
|
* [reqIndicators](#reqindicators)
|
|
* [reqIndicatorClass](#reqindicatorclass)
|
|
* [valFieldsOn](#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.
|
|
|
|
```html
|
|
<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`](#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.
|
|
|
|
```html
|
|
<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.
|
|
|
|
```html
|
|
<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-validation` attribute to a field that's value is a JSON object with an
|
|
[`optional`](#optional) property value set to `true`.
|
|
|
|
```html
|
|
<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.
|
|
|
|
```css
|
|
.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`](https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event),
|
|
[`change`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event),
|
|
or [`input`](https://developer.mozilla.org/en-US/docs/Web/API/Element/input_event).
|
|
|
|
> Individual field validation can be disable by setting
|
|
[`onlyOnSubmit`](#onlyOnSubmit) to true.
|
|
|
|
## Field Options
|
|
|
|
* [optional](#optional)
|
|
* [pattern](#pattern)
|
|
* [patternMessage](#patternmessage)
|
|
* [valueSrc](#valuesrc)
|
|
|
|
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.
|
|
|
|
```html
|
|
<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`](#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`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern)
|
|
attribute. It is recommended to also provide an error message to display when
|
|
the value does not match `pattern` by providing a [`patternMessage`](#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`](#pattern).
|
|
|
|
> If not provided with [`pattern`](#pattern) the 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](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Forms/How_to_build_custom_form_controls).
|
|
See [here](#custom-form-controls) for more information.
|