page.mdx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import { pageMetadata } from "@/lib/page-metadata"
  2. export const metadata = pageMetadata("docs/validation")
  3. # Validation
  4. Validate form inputs with built-in and custom functions.
  5. ## Built-in Validators
  6. json-render includes common validation functions:
  7. - `required` — Value must be non-empty
  8. - `email` — Valid email format
  9. - `minLength` — Minimum string length
  10. - `maxLength` — Maximum string length
  11. - `pattern` — Match a regex pattern
  12. - `min` — Minimum numeric value
  13. - `max` — Maximum numeric value
  14. ## Using Validation in JSON
  15. 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):
  16. ```json
  17. {
  18. "type": "TextField",
  19. "props": {
  20. "label": "Email",
  21. "value": { "$bindState": "/form/email" },
  22. "checks": [
  23. { "type": "required", "message": "Email is required" },
  24. { "type": "email", "message": "Invalid email format" }
  25. ],
  26. "validateOn": "blur"
  27. }
  28. }
  29. ```
  30. ## Validation with Parameters
  31. ```json
  32. {
  33. "type": "TextField",
  34. "props": {
  35. "label": "Password",
  36. "value": { "$bindState": "/form/password" },
  37. "checks": [
  38. { "type": "required", "message": "Password is required" },
  39. {
  40. "type": "minLength",
  41. "args": { "min": 8 },
  42. "message": "Password must be at least 8 characters"
  43. },
  44. {
  45. "type": "pattern",
  46. "args": { "pattern": "[A-Z]" },
  47. "message": "Must contain at least one uppercase letter"
  48. }
  49. ]
  50. }
  51. }
  52. ```
  53. ## Custom Validation Functions
  54. Define custom validators in your catalog's `functions` field. The catalog itself is framework-agnostic — only the `schema` import varies by platform:
  55. ```typescript
  56. import { defineCatalog } from '@json-render/core';
  57. import { schema } from '@json-render/react/schema'; // or '@json-render/react-native/schema'
  58. import { z } from 'zod';
  59. const catalog = defineCatalog(schema, {
  60. components: { /* ... */ },
  61. functions: {
  62. isValidPhone: {
  63. description: 'Validates phone number format',
  64. },
  65. isUniqueEmail: {
  66. description: 'Checks if email is not already registered',
  67. },
  68. },
  69. });
  70. ```
  71. ## Usage with React
  72. In `@json-render/react`, use `ValidationProvider` to supply implementations for your custom validators:
  73. ```tsx
  74. import { ValidationProvider } from '@json-render/react';
  75. function App() {
  76. const customValidators = {
  77. isValidPhone: (value) => {
  78. const phoneRegex = /^\+?[1-9]\d{1,14}$/;
  79. return phoneRegex.test(value);
  80. },
  81. isUniqueEmail: async (value) => {
  82. const response = await fetch(`/api/check-email?email=${value}`);
  83. const { available } = await response.json();
  84. return available;
  85. },
  86. };
  87. return (
  88. <ValidationProvider customFunctions={customValidators}>
  89. {/* Your UI */}
  90. </ValidationProvider>
  91. );
  92. }
  93. ```
  94. ### Using in Components
  95. The `useFieldValidation` and `useBoundProp` hooks wire validation into your registry components. Validation uses the path from `bindings?.value` (the bound state path):
  96. ```tsx
  97. import { useFieldValidation, useBoundProp } from '@json-render/react';
  98. function TextField({ props, bindings }) {
  99. const [value, setValue] = useBoundProp(props.value, bindings?.value);
  100. const { errors, isValid, validate, touch, clear } = useFieldValidation(
  101. bindings?.value ?? null,
  102. { checks: props.checks, validateOn: props.validateOn }
  103. );
  104. return (
  105. <div>
  106. <label>{props.label}</label>
  107. <input
  108. value={value || ''}
  109. onChange={(e) => setValue(e.target.value)}
  110. onBlur={() => validate()}
  111. />
  112. {errors.map((error, i) => (
  113. <p key={i} className="text-red-500 text-sm">{error}</p>
  114. ))}
  115. </div>
  116. );
  117. }
  118. ```
  119. See the [@json-render/react API reference](/docs/api/react) for full `ValidationProvider` and `useFieldValidation` documentation.
  120. ## Validation Timing
  121. Control when validation runs with `validateOn`:
  122. - `change` — Validate on every input change
  123. - `blur` — Validate when field loses focus
  124. - `submit` — Validate only on form submission
  125. ## Next
  126. Learn about [generation modes](/docs/generation-modes).