import { pageMetadata } from "@/lib/page-metadata" export const metadata = pageMetadata("docs/validation") # Validation Validate form inputs with built-in and custom functions. ## Built-in Validators json-render includes common validation functions: - `required` — Value must be non-empty - `email` — Valid email format - `minLength` — Minimum string length - `maxLength` — Maximum string length - `pattern` — Match a regex pattern - `min` — Minimum numeric value - `max` — Maximum numeric value ## Using Validation in JSON Use `{ "$bindState": "/path" }` on the value prop for two-way binding. Validation checks run against the value at the bound path (available as `bindings?.value` in components): ```json { "type": "TextField", "props": { "label": "Email", "value": { "$bindState": "/form/email" }, "checks": [ { "type": "required", "message": "Email is required" }, { "type": "email", "message": "Invalid email format" } ], "validateOn": "blur" } } ``` ## Validation with Parameters ```json { "type": "TextField", "props": { "label": "Password", "value": { "$bindState": "/form/password" }, "checks": [ { "type": "required", "message": "Password is required" }, { "type": "minLength", "args": { "min": 8 }, "message": "Password must be at least 8 characters" }, { "type": "pattern", "args": { "pattern": "[A-Z]" }, "message": "Must contain at least one uppercase letter" } ] } } ``` ## Custom Validation Functions Define custom validators in your catalog's `functions` field. The catalog itself is framework-agnostic — only the `schema` import varies by platform: ```typescript import { defineCatalog } from '@json-render/core'; import { schema } from '@json-render/react'; // or '@json-render/react-native' import { z } from 'zod'; const catalog = defineCatalog(schema, { components: { /* ... */ }, functions: { isValidPhone: { description: 'Validates phone number format', }, isUniqueEmail: { description: 'Checks if email is not already registered', }, }, }); ``` ## Usage with React In `@json-render/react`, use `ValidationProvider` to supply implementations for your custom validators: ```tsx import { ValidationProvider } from '@json-render/react'; function App() { const customValidators = { isValidPhone: (value) => { const phoneRegex = /^\+?[1-9]\d{1,14}$/; return phoneRegex.test(value); }, isUniqueEmail: async (value) => { const response = await fetch(`/api/check-email?email=${value}`); const { available } = await response.json(); return available; }, }; return ( {/* Your UI */} ); } ``` ### Using in Components The `useFieldValidation` and `useBoundProp` hooks wire validation into your registry components. Validation uses the path from `bindings?.value` (the bound state path): ```tsx import { useFieldValidation, useBoundProp } from '@json-render/react'; function TextField({ props, bindings }) { const [value, setValue] = useBoundProp(props.value, bindings?.value); const { errors, isValid, validate, touch, clear } = useFieldValidation( bindings?.value ?? null, { checks: props.checks, validateOn: props.validateOn } ); return (
setValue(e.target.value)} onBlur={() => validate()} /> {errors.map((error, i) => (

{error}

))}
); } ``` See the [@json-render/react API reference](/docs/api/react) for full `ValidationProvider` and `useFieldValidation` documentation. ## Validation Timing Control when validation runs with `validateOn`: - `change` — Validate on every input change - `blur` — Validate when field loses focus - `submit` — Validate only on form submission ## Next Learn about [generation modes](/docs/generation-modes).