1. Interactive Playground (Shipping Schedule)
One schema validates the whole payload — top-level fields, the nested operator group, and every row of the editable ports table (per-td inputs, validated cell-by-cell on blur). Leave fields empty, duplicate a port code, or set a type to International without a customs code, then hit Validate schedule — the toast's error tree navigates straight to each field.
2. Quick Start
execute(data, rules) validates everything and returns the resulting validity, so a submit handler is one guard clause. getFieldError(path) binds straight to an input's error prop; validateField on input re-runs the field's rules on every keystroke, so the error updates live instead of lingering stale until the field blurs.
- At least 8 characters
- One uppercase letter
- One lowercase letter
- One number
3. Field-Level Validation
validateField(path) re-runs one field's rules without touching any other field's errors — the on-blur flow, and the only sane way to validate per-cell in an editable table. Paths use dot + [index] notation however deep the field sits. For fields with unique, the whole column is re-checked so a fixed duplicate clears its mirror error in the other row too.
4. Toast Summary & Navigation
getErrorList() emits the error tree in exactly the shape the toast's errorList renders — groups become nested items, array rows become numbered children (Ports #2), and every leaf navigates. Mark inputs with data-validate-field="<path>" (or an id) and clicking an item scrolls to and focuses the field. Try it in the playground above.
5. Custom Rules, Validators & Messages
Register app-wide validators once via useDataValidator({ validators }), override default messages globally or per field, and use the per-field custom rule as the escape hatch for anything else — it receives the value plus a context with the whole payload, the owning object, and the row index.
API Reference
Complete specifications for useDataValidator's options, rules, and returned state.