validation-enhancer
v1.0.3
Published
The easiest, most lightweight validation system.
Readme
<validation-enhancer>
The easiest, most lightweight validation system.
npm install validation-enhancer
yarn add validation-enhancerTry the LIVE DEMO!
Enhance
Wrap any HTML form in <validation-enhancer> to enhance its validation.
<validation-enhancer> is a web component that brings native HTML validation to life - with the UX you want right out of the box
<validation-enhancer-zod> is the same thing, but zod validates the form
Easy to Use!
- Literally just wrap a form in
<validation-enhancer> - Or wrap a form in
<validation-enhancer-zod>and pass your zod schema tosetZodSchema()
Great UX!
- Displays error messages next to each input
- Shows errors on focus out and submit
- Clears errors immediately when the user corrects their input
- Works with screen readers out of the box
- Focuses the first invalid field on submit, and scrolls to its label
- Progressive enhancement as standard - in the event of an error browser html validation will still function
Customisable!
- Adds
.valid/.invalidCSS classes on inputs as the user interacts, you control the style - Custom error messages in HTML attributes
- Completely customisable validation using
setCustomValidity() - Validate custom elements too!
Step 1
Wrap <validation-enhancer> around your form
<validation-enhancer>
<form>
<label for="email">Email</label>
<input type="email" id="email" required />
<button type="submit">Submit</button>
</form>
</validation-enhancer>Step 2
Assign each input an error display element using the aria-errormessage attribute
<validation-enhancer>
<form>
<label for="email">Email</label>
<input type="email" id="email" required aria-errormessage="email-error" />
<div id="email-error"></div>
<button type="submit">Submit</button>
</form>
</validation-enhancer>Step 3
Style .valid, .invalid, and the validation message.
.valid {
border-color: green;
}
.invalid {
border-color: red;
}Done!
That's all it takes to enhance your form!
<validation-enhancer>
<form>
<label for="email">Email</label>
<input type="email" id="email" aria-errormessage="email-error" required />
<div id="email-error" style="color:red"></div>
<button type="submit">Submit</button>
</form>
</validation-enhancer>
<style>
.valid {
border-color: green;
}
.invalid {
border-color: red;
}
</style>
<script type="module" src="validation-enhancer.min.js"></script>Zod integration
Use a Zod schema as the single source of truth for validation. The zod schema will override any HTML attributes.
<validation-enhancer-zod>
<form>
<label for="email">Email</label>
<input type="email" name="email_field" required aria-errormessage="email-error" />
<div id="email-error"></div>
<button type="submit">Submit</button>
</form>
</validation-enhancer-zod>
<script>
import { z } from "zod";
/* Define Zod Schema */
const schema = z.object({
/* Reference inputs by name attribute */
email_field: z.string()
.min(1, "Email is required.")
.email("Please enter a valid email address."),
});
/* Run when the script is loaded */
customElements.whenDefined("validation-enhancer-zod").then(() => {
const validationEnhancerZod = document.querySelector("validation-enhancer-zod");
validationEnhancerZod.setZodSchema(schema);
});
</script>Inputs are matched to schema fields by their name attribute — inputs without a name are skipped by zod validation.
Use getZodSchema() to read back the current schema.
Install
npm install validation-enhancer
yarn add validation-enhancerImport
import "validation-enhancer";
import "validation-enhancer-zod";Or copy dist/validation-enhancer.min.js into your project and load it directly:
<script type="module" src="validation-enhancer.min.js"></script>
<script type="module" src="validation-enhancer-zod.min.js"></script>Custom errors
<input
type="email"
id="email"
required
aria-errormessage="email-error"
validation-valueMissing="An email address is required."
validation-typeMismatch="That doesn't look like a valid email."
>Override the browser's default validation text by adding attributes that match validity state keys. Both validation-* and data-validation-* forms are accepted.
Attributes are checked in the following order, to mimic default browser behaviour. Bare attributes are checked before data- attributes.
| Attribute | Triggered when |
| -------------------------------- | ------------------------------------- |
| validation-valueMissing | Required field is empty |
| validation-typeMismatch | Value doesn't match type (eg email) |
| validation-patternMismatch | Value doesn't match pattern |
| validation-tooLong | Value exceeds maxlength |
| validation-tooShort | Value is shorter than minlength |
| validation-rangeUnderflow | Number is below min |
| validation-rangeOverflow | Number is above max |
| validation-stepMismatch | Number doesn't match step |
| validation-badInput | Browser can't parse the input |
If no custom message is set, the browser's built-in validationMessage is used.
<validation-enhancer-zod> gets its error messages from the zod schema instead.
Custom message prefix
The default prefix is "validation". Change it with the message-prefix attribute to avoid conflicts or match your own naming convention:
<validation-enhancer message-prefix="custom">
<form>
<input
required
custom-valueMissing="Please fill this out."
aria-errormessage="msg"
>
<!-- also accepts data-custom-valueMissing -->
<div id="msg"></div>
</form>
</validation-enhancer>CSS classes
The component adds these classes to each validated input and also manages aria-invalid:
| Class / attribute | When |
| --------------------- | -------------------------- |
| .valid | Input passes validation |
| .invalid | Input fails validation |
| aria-invalid="true" | Input fails validation |
Style them however you like:
.valid {
border-color: green;
}
.invalid {
border-color: red;
}Custom class names
By default the component uses .valid and .invalid. Override them with the valid-class and invalid-class attributes:
<validation-enhancer valid-class="ok" invalid-class="error">
<form>
<!-- inputs will receive ".ok" / ".error" when validating -->
</form>
</validation-enhancer>input.ok { border-color: green; }
input.error { border-color: red; }Custom aria-live urgency
By default the component sets aria-live="polite" on error message elements. Override it with message-aria-live:
<validation-enhancer message-aria-live="assertive">Custom message target attribute
By default, the component locates each input's companion message element via aria-errormessage. If your markup uses a different attribute, set message-target-attr. For example, some older screenreaders might respond better to "aria-describedby" than the newer "aria-errormessage":
<validation-enhancer message-target-attr="aria-describedby">
<form>
<input required aria-describedby="email-error">
<div id="email-error"></div>
</form>
</validation-enhancer>Inputs that lack the configured attribute fall back to the browser's native reportValidity().
Scroll behaviour
On submit, focuses the first invalid field and scrolls to its label. The scroll can be configured with attributes on <validation-enhancer>:
| Attribute | Effect |
| -------------------- | ---------------------------------------------------------------------- |
| scroll-behavior | ScrollBehavior string passed to scrollIntoView, default "smooth" |
| scroll-block | block option for scrollIntoView |
| scroll-inline | inline option for scrollIntoView |
| scroll-align-to-top| When present, passes a boolean to scrollIntoView instead of options object ("false" → false, anything else → true) |
| scroll-container | CSS selector for a custom scroll container — scrolls that element instead of calling scrollIntoView |
Programmatic value changes
The component listens for change, focusout, and keyup events. If you set an input's value in JavaScript, dispatch a change event so validation picks it up:
input.value = "new value";
input.dispatchEvent(new Event("change", { bubbles: true }));The web component registers newly-added forms and fields, if they are modified after instantiation.
Versions
dist/validation-enhancer.js: Unminified, for development
dist/validation-enhancer.min.js: Minified, for production
dist/validation-enhancer.compat.min.js: ES2017 build minified, for production - compatible with older browsers
dist/validation-enhancer-zod.js: Comes with main validation-enhancer included. Unminified, for development
dist/validation-enhancer-zod.min.js: Comes with main validation-enhancer included. Minified, for production
dist/validation-enhancer-zod.compat.min.js: Comes with main validation-enhancer included. ES2017 build minified, for production - compatible with older browsers
Development
npm install # install dependencies
npm run build # compile to dist/
npm run demo # open demo page
npm test # run tests (vitest)
npm run test:e2e # run tests (playwright)
npm run lint # eslint
npm run format # prettier --write