HTML5 Form Validation & htmx:validation:failed Event Hooks
- Last updated
- Prerequisites:
- HTML5 Constraint Validation API (`checkValidity`, `reportValidity`)
- HTMX Events
- htmx
- validation
- html5
- events
- forms
- htmx-validation
Read at your depth
The practical view
HTMX natively honors standard HTML5 form validation attributes (`required`, `pattern`, `minlength`, `type="email"`). When a form or button with `hx-post` is submitted, HTMX calls `form.checkValidity()`. If invalid, the AJAX request is blocked and the browser displays native error bubbles. You can listen to `htmx:validation:validate` or `htmx:validation:failed` in JavaScript to attach custom validation rules.
The same idea in other frameworks
React Hook Form / Zod resolver client validation.Angular `Validators.required` on `FormControl`.VeeValidate / Vuelidate form validation schemas.Native HTML5 `required` + `htmx:validation:validate` event.Legacy vs modern
Heavy Client-Side Validation Library vs Native HTML5 + HTMX Event Hooks
Third-party validation bundles add 50KB of JS; HTMX utilizes native HTML5 validation with custom event hooks.
if (!validateRegex(email)) { showError(); return; } // ❌ Manual regex checks in JS<input type="email" required minlength="5" /> // ✅ NEW: Native constraint validationInterview gotchas
Context
Interviewers test your knowledge of server-side-only validation workflows.
The mechanical answer
Add the standard HTML5 **`novalidate`** attribute to the `<form>` element (or `hx-validate="false"` on the element). This causes HTMX to skip `checkValidity()` checks and submit the form data to the server immediately, allowing server-side validation to return formatted error messages in HTML.
Trap
Without `novalidate`, the browser will prevent submission and show native tooltips, preventing the server from receiving the invalid input.
Context
Checks knowledge of HTMX lifecycle event listeners.
The mechanical answer
Listen to the **`htmx:validation:failed`** event: `document.body.addEventListener('htmx:validation:failed', (evt) => { evt.detail.elt.classList.add('is-invalid'); })`. This allows you to apply custom CSS classes and UI error badges whenever validation blocks a request.
Trap
Remember to remove the error class on `htmx:validation:validate` when the user corrects their input.