# TanStack Form [TanStack Form](https://tanstack.com/form) accepts any Standard Schema V1 as a form or field validator. `ata-validator` implements Standard Schema natively, so a `Validator` instance plugs straight in. ## Install ```bash npm install ata-validator @tanstack/react-form ``` ## Form-level validation ```tsx import { useForm } from '@tanstack/react-form' import { Validator } from 'ata-validator' const userFormSchema = new Validator({ type: 'object', properties: { name: { type: 'string', minLength: 1, maxLength: 100 }, email: { type: 'string' }, age: { type: 'integer', minimum: 13 }, }, required: ['name', 'email'], }) export function UserForm() { const form = useForm({ defaultValues: { name: '', email: '', age: 0 }, validators: { onChange: userFormSchema, }, onSubmit: async ({ value }) => { console.log(value) }, }) return (
{ e.preventDefault(); form.handleSubmit() }}> (
field.handleChange(e.target.value)} /> {field.state.meta.errors.length > 0 && ( {field.state.meta.errors.join(', ')} )}
)} /> {/* ... other fields ... */} ) } ``` ## Field-level validation Pass a single-field Validator to a specific `form.Field`: ```tsx const emailSchema = new Validator({ type: 'string', minLength: 5, maxLength: 200 }) /* ... */} /> ``` ## Using compiled schemas for types Pair TanStack Form with `ata compile` to get a type-narrowed `value` on submit: ```bash npx ata compile schemas/user-form.json -o src/user-form.validator.mjs --name UserForm ``` ```tsx import { Validator } from 'ata-validator' import type { UserForm } from './schemas/user-form.validator.mjs' import userFormSchemaJson from './schemas/user-form.json' with { type: 'json' } const userFormSchema = new Validator(userFormSchemaJson) export function MyForm() { const form = useForm({ defaultValues: { name: '', email: '', age: 0 }, validators: { onChange: userFormSchema }, onSubmit: async ({ value }) => { // `value` is UserForm saveUser(value) }, }) // ... } ``` ## Error shape TanStack Form reads the Standard Schema `issues` array and surfaces them on `field.state.meta.errors`. Each issue has a `message` and `path`, and the form maps path to field automatically. Default error messages come from ata's ajv-compatible defaults ("must be >= 1", "must be string", etc.). To customize, intercept in `onChangeAsync` or use a validator with `abortEarly` off and post-process. ## Notes - Works the same with Solid / Vue / Svelte adapters of TanStack Form. - For forms with complex cross-field rules (if/then/else), keep those in the schema; Standard Schema surfaces them as issues with the correct path. - For very high-frequency validation (on every keystroke), consider a single `onSubmit`-level validator instead of `onChange` to keep keystroke latency low.