Enhancement
FormEnhancer
Accessible error messages for the browser's own form validation
- Import
@parallelogram-js/core/components/FormEnhancer- Selector
form[data-form-enhancer]
Playground
Booking form
Leave a field empty or submit to see the messages.
<form data-form-enhancer class="form" action="#booked">
<div class="form__group">
<label class="form__label" for="guest-name">Name</label>
<div class="form__control">
<input id="guest-name" name="name" required minlength="2" autocomplete="name">
</div>
</div>
<div class="form__group">
<label class="form__label" for="guest-email">Email</label>
<div class="form__control">
<input id="guest-email" name="email" type="email" required autocomplete="email"
data-form-enhancer-message-value-missing="Tell us where to send your confirmation">
<p data-error-for="email" hidden></p>
</div>
</div>
<div class="form__group">
<label class="form__label" for="guest-party">Party size</label>
<div class="form__control">
<input id="guest-party" name="party" type="number" min="1" max="12" required>
</div>
</div>
<div class="form__actions">
<button type="submit">Book</button>
</div>
</form>
Use the example to see the events it sends.
About
Fields declare their rules with native attributes (required, type, minlength, maxlength, min, max, step and pattern), so the form still validates when scripts don't run. Once mounted, FormEnhancer sets novalidate on the form and shows the messages itself: after the user leaves a field they changed, and for every field when they submit. A blocked submission moves focus to the first invalid field.
Each error is written to the form's [data-error-for] element for that field, or to one created after it. The field gets aria-invalid="true" and an aria-describedby link to the message. Messages come from the browser's localised validationMessage unless the field supplies its own. Custom rules use setCustomValidity() on the field.
Usage
Register the component and the framework loads it the first time a page contains form[data-form-enhancer].
import { Parallelogram } from '@parallelogram-js/core';
const app = Parallelogram.create();
app.components.add('form[data-form-enhancer]', () => import('@parallelogram-js/core/components/FormEnhancer'));
app.run();
The framework is optional. FormEnhancer.enhanceAll() mounts the component on every matching element by itself, for a page that wants one enhancement rather than a framework:
import FormEnhancer from '@parallelogram-js/core/components/FormEnhancer';
FormEnhancer.enhanceAll();
It takes a selector and the component's options, and returns the instance it mounted them with. What it leaves out is what the framework adds: loading a component only on the pages that use it, mounting again after a page swap, and ordering with dependsOn.
Attributes
| Name | Type | Default | Description |
|---|---|---|---|
data-form-enhancer | flag | none | Marks the form On the form. |
data-form-enhancer-validate-on-input | boolean | true | Re-check a field that shows an error as it is edited For every instance, FormEnhancer.defaults.validateOnInput. |
data-form-enhancer-validate-on-blur | boolean | true | Check a changed field when the user leaves it For every instance, FormEnhancer.defaults.validateOnBlur. |
data-form-enhancer-show-errors-immediately | boolean | false | Check fields while the user types For every instance, FormEnhancer.defaults.showErrorsImmediately. |
data-form-enhancer-validate-debounce | number | 300 | Typing pause in milliseconds before checking, when errors show immediately For every instance, FormEnhancer.defaults.debounce. |
data-form-enhancer-error-class | string | is-invalid | Class added to invalid fields For every instance, FormEnhancer.defaults.errorClass. |
data-form-enhancer-valid-class | string | is-valid | Class added to checked fields that are valid For every instance, FormEnhancer.defaults.validClass. |
data-form-enhancer-message-class | string | form__error | Class on a message element the form didn't supply itself For every instance, FormEnhancer.defaults.messageClass. |
data-form-enhancer-message | string | none | The message for any failure On a field. |
data-form-enhancer-message-<constraint> | string | none | The message for one constraint: value-missing, type-mismatch, bad-input, pattern-mismatch, too-short, too-long, range-underflow, range-overflow or step-mismatch On a field. |
data-error-for | string | none | The field's name On the element that shows a field's error. |
Events
| Name | Detail | Description |
|---|---|---|
form-enhancer:mounted | { element: HTMLFormElement; fieldCount: number } | The form was set up DOM event and event bus |
form-enhancer:submit-blocked | { element: HTMLFormElement; errors: Array<[string, string]> } | A submission was stopped; errors pairs each field name with its message DOM event and event bus |
form-enhancer:submit-valid | { element: HTMLFormElement } | Every field passed and the submission goes ahead DOM event and event bus |