LEARNING OBJECTIVES ⌵
- Master the complete Constraint Validation API methods:
checkValidity(),reportValidity(), andsetCustomValidity(). - Deconstruct all 10 individual boolean flags of the
ValidityStateinterface. - Understand the difference between silent validity evaluation (
checkValidity()) and UI-rendering evaluation (reportValidity()). - Architect a scalable, production-grade error message dispatcher that translates low-level
ValidityStateflags into localized UI strings. - Batch-audit entire forms via
HTMLFormElement.elementsandform.checkValidity().
📖 The Mental Model & Story (Intuitive Foundation)
Imagine sitting in the cockpit of a commercial airliner performing a pre-flight diagnostic check:
+-----------------------------------------------------------------------------+
| AIRCRAFT AVIONICS DIAGNOSTIC CONSOLE |
+-----------------------------------------------------------------------------+
| |
| [ PILOT RUNS DIAGNOSTIC ] ──► checkValidity() |
| │ |
| ▼ |
| ┌───────────────────────────────────────────────────┐ |
| │ 10-POINT SENSOR STATUS MATRIX │ |
| ├─────────────────────────┬─────────────────────────┤ |
| │ [🟢] valueMissing │ [🔴] rangeUnderflow │ |
| │ [🟢] typeMismatch │ [🟢] rangeOverflow │ |
| │ [🟢] patternMismatch │ [🟢] stepMismatch │ |
| │ [🟢] tooShort │ [🟢] badInput │ |
| │ [🟢] tooLong │ [🟢] customError │ |
| └─────────────────────────┴─────────────────────────┘ |
| │ |
| ▼ |
| SUMMARY: validity.valid = false |
| ACTION: reportValidity() ──► Rings alarm & points directly to Fuel Gauge |
| |
+-----------------------------------------------------------------------------+
An aircraft computer doesn't just show a generic "System Broken" red light. It monitors 10 independent sensor channels: Fuel Level (rangeUnderflow), Oxygen Pressure (rangeOverflow), Navigation Format (patternMismatch), Emergency Beacon Missing (valueMissing), etc.
In HTML5, every form control contains a ValidityState object containing 10 discrete boolean flags. As an engineer, you can inspect these individual flags programmatically to diagnose the exact reason an input failed and display targeted, human-friendly guidance.
Technical Deep Dive & Specifications
2.1 The Complete 10-Flag ValidityState Interface
Under the WHATWG HTML Standard (§ 4.10.21.2), element.validity is a read-only ValidityState interface containing exactly 10 constraint flags and 1 summary flag:
+----------------------------------------------------------------------------------------------------+
| THE 10 VALIDITYSTATE FLAGS REFERENCE |
+----------------------------------------------------------------------------------------------------+
FLAG TYPE CORRESPONDING CONSTRAINT RULE
───────────────────────────────────────────────────────────────────────────────────────────────────
1. valueMissing boolean Element is 'required' and value is empty.
2. typeMismatch boolean Value violates syntax for type="email" or type="url".
3. patternMismatch boolean Value does not match the 'pattern' regular expression.
4. tooShort boolean Value length is non-zero but strictly less than 'minlength'.
5. tooLong boolean Value length exceeds 'maxlength' (e.g. via DOM assignment).
6. rangeUnderflow boolean Numerical/temporal value is strictly less than 'min'.
7. rangeOverflow boolean Numerical/temporal value is strictly greater than 'max'.
8. stepMismatch boolean Value does not fit the stepping interval '(val - base) % step'.
9. badInput boolean Browser cannot parse input (e.g. typing letters into type="number").
10. customError boolean setCustomValidity() was called with a non-empty error string.
───────────────────────────────────────────────────────────────────────────────────────────────────
*. valid boolean SUMMARY: true if and only if ALL 10 flags above are FALSE.
2.2 Methods of the Constraint Validation API
| Method | Target | Return Value | Fires invalid Event? |
Displays Native UI Bubble? |
|---|---|---|---|---|
element.checkValidity() |
Single Input | boolean |
Yes (if invalid) | No (Silent) |
element.reportValidity() |
Single Input | boolean |
Yes (if invalid) | Yes (Focuses & renders bubble) |
element.setCustomValidity(msg) |
Single Input | void |
N/A | Updates message & customError flag |
form.checkValidity() |
Entire <form> |
boolean |
Yes (on all invalid inputs) | No (Silent) |
form.reportValidity() |
Entire <form> |
boolean |
Yes (on all invalid inputs) | Yes (Focuses first invalid) |
const form = document.querySelector('form');
// 1. Silent check (Great for enabling/disabling submit buttons or tabs)
if (form.checkValidity()) {
console.log('All inputs in form are completely valid!');
}
// 2. Interactive check (Triggers native browser error bubble on first failing element)
if (!form.reportValidity()) {
console.log('Submission blocked; browser focused first invalid control.');
}
2.3 The Universal Error Message Resolver Pattern
Instead of relying on browser default strings, senior engineers map ValidityState flags to application-specific dictionaries:
function resolveErrorMessage(input) {
const v = input.validity;
if (v.valid) return '';
if (v.valueMissing) return `${input.name} is mandatory. Please provide a value.`;
if (v.typeMismatch) return `Please enter a valid ${input.type} format.`;
if (v.patternMismatch) return input.title || `Format does not match required pattern.`;
if (v.tooShort) return `Must be at least ${input.minLength} characters (currently ${input.value.length}).`;
if (v.tooLong) return `Cannot exceed ${input.maxLength} characters.`;
if (v.rangeUnderflow) return `Value must be at least ${input.min}.`;
if (v.rangeOverflow) return `Value cannot exceed ${input.max}.`;
if (v.stepMismatch) return `Please select a valid interval step (${input.step}).`;
if (v.badInput) return `Please enter a valid number or date.`;
if (v.customError) return input.validationMessage;
return 'Invalid input value.';
}
💻 Interactive Code Playground
Starter Code
The following enterprise diagnostic console allows you to interact with multiple controls and inspect all 10 ValidityState flags in a real-time matrix.
Line-by-Line Code Breakdown
- Lines 131-135 (
FLAGSarray): Declares all 10 standard WHATWGValidityStateflags in the exact specification taxonomy. - Lines 137-160 (
renderMatrix()): Queriesinput.validity[flag]dynamically to illuminate the real-time LED diagnostic board. - Lines 163-176 (
resolveErrorMessage()): The enterprise error resolver function that translates raw boolean flags into user-friendly localized copy. - Lines 183-191 (
form.checkValidity()vsform.reportValidity()): Demonstrates the difference between silent evaluation and interactive popup reporting.
Expected Browser Render Output
+------------------------------------+ +------------------------------------+
| Form Inspector | | 10-Point ValidityState Matrix |
| Select an input to stream flags... | | Inspecting: [Email] (Value: "") |
| | | |
| 1. Email (required, type=email) | | [🔴 TRUE ] valueMissing |
| [ ] | | [🟢 FALSE] typeMismatch |
| | | [🟢 FALSE] patternMismatch |
| 2. Code (pattern: [A-Z]{3}-\d{3}) | | [🟢 FALSE] tooShort |
| [ ] | | [🟢 FALSE] tooLong |
| | | [🟢 FALSE] rangeUnderflow |
| [ form.reportValidity() ] | | [🟢 FALSE] rangeOverflow |
| [ form.checkValidity() ] | | [⛔ FALSE] SUMMARY: validity.valid |
+------------------------------------+ +------------------------------------+🏋️ Hands-On Exercise
🎯 The Challenge: Build an Accessible Form Audit Engine
Scenario: You are building an enterprise forms library. When a user submits an invalid form, instead of showing native browser bubbles, your engine must:
- Prevent default submission.
- Iterate through all submittable elements in
form.elements. - Collect all invalid inputs using
input.validity.valid === false. - Generate an accessible error summary list at the top of the form with anchor links focusing each invalid field.
Instructions:
- Create a form with 3 diverse inputs (Name:
required, Age:min="18" max="99", Email:type="email" required). - Add a container
<div id="errorSummary" role="alert" tabIndex="-1"></div>at the top of the form. - On submit, check
form.checkValidity(). If false, build a<ul>of error messages inside#errorSummarywith clickable links that.focus()the corresponding input.
🏁 Starter Code Sandbox
⚠️ Common Pitfalls
- Confusing
checkValidity()withreportValidity():checkValidity()is silent and never renders visual bubbles. If you want the browser to highlight and scroll to the invalid field, usereportValidity(). - Attempting to Mutate
ValidityState: Writinginput.validity.valid = false. Thevalidityobject is strictly read-only. You must usesetCustomValidity()to programmatically modify validity state. - The
badInputGotcha: When a user types non-numeric characters (like12abc) into<input type="number">,input.valueis evaluated as""(empty string) in JavaScript, butvalidity.badInputwill betrue. Always checkvalidity.badInputbefore assuming the field is empty!
💡 Pro Tips
- Batch Validation via
HTMLFormControlsCollection: Iterateform.elementswithArray.from(form.elements)to run automated pre-flight security sweeps before serializing intoFormDataor JSON. - Silent State Observers: Use
input.checkValidity()insideinputevent listeners to dynamically toggle submit buttondisabledstates without bothering the user with intrusive popups.
📌 Key Takeaways
- 10
ValidityStateFlags: Provide granular insight into the exact failure condition (valueMissing,typeMismatch,patternMismatch,tooShort,tooLong,rangeUnderflow,rangeOverflow,stepMismatch,badInput,customError). validity.valid: True if and only if all 10 individual flags are false.checkValidity()vsreportValidity():checkValidity()performs silent evaluation;reportValidity()performs evaluation AND renders the native error tooltip.badInputFlag: Catches unparseable numerical and date entries whereinput.valuereturns empty string.- Form Batch Auditing:
form.checkValidity()checks all candidate elements (willValidate === true) in DOM tree order. - --