0
# Form Component
1
2
The Form component is the main React component that renders JSON schemas as interactive forms with validation, customization, and event handling capabilities.
3
4
## Capabilities
5
6
### Form Class
7
8
Main form component that converts JSON Schema definitions into interactive React forms.
9
10
```typescript { .api }
11
/**
12
* Main form component that renders JSON schemas as interactive forms
13
* @template T - Type of form data
14
* @template S - Type of JSON schema (extends StrictRJSFSchema)
15
* @template F - Type of form context (extends FormContextType)
16
*/
17
export default class Form<
18
T = any,
19
S extends StrictRJSFSchema = RJSFSchema,
20
F extends FormContextType = any
21
> extends Component<FormProps<T, S, F>, FormState<T, S, F>> {
22
/** Programmatically submit the form */
23
submit(): void;
24
/** Validate current form data and return whether it's valid */
25
validateForm(): boolean;
26
/** Reset form to initial state */
27
reset(): void;
28
/** Focus on the field that has the given error */
29
focusOnError(error: RJSFValidationError): void;
30
}
31
```
32
33
**Usage Examples:**
34
35
```typescript
36
import Form from "@rjsf/core";
37
import validator from "@rjsf/validator-ajv8";
38
39
// Basic form with validation
40
const MyForm = () => {
41
const schema = {
42
type: "object",
43
properties: {
44
name: { type: "string", title: "Full Name" },
45
age: { type: "number", title: "Age", minimum: 0 }
46
},
47
required: ["name"]
48
};
49
50
return (
51
<Form
52
schema={schema}
53
validator={validator}
54
onSubmit={({ formData }) => console.log(formData)}
55
/>
56
);
57
};
58
59
// Form with custom validation and error handling
60
const AdvancedForm = () => {
61
const [errors, setErrors] = useState([]);
62
const formRef = useRef<Form>(null);
63
64
const customValidate = (formData, errors) => {
65
if (formData.age < 18) {
66
errors.age.addError("Must be 18 or older");
67
}
68
return errors;
69
};
70
71
const handleSubmit = ({ formData }) => {
72
if (formRef.current?.validateForm()) {
73
console.log("Valid form data:", formData);
74
}
75
};
76
77
return (
78
<Form
79
ref={formRef}
80
schema={schema}
81
validator={validator}
82
customValidate={customValidate}
83
onSubmit={handleSubmit}
84
onError={setErrors}
85
showErrorList="top"
86
/>
87
);
88
};
89
```
90
91
### Form Props Interface
92
93
Complete configuration interface for the Form component with all available options.
94
95
```typescript { .api }
96
interface FormProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
97
// Core required props
98
/** JSON schema object defining the form structure */
99
schema: S;
100
/** Validator implementation for form validation */
101
validator: ValidatorType<T, S, F>;
102
103
// Data management
104
/** UI schema for customizing form appearance and behavior */
105
uiSchema?: UiSchema<T, S, F>;
106
/** Initial or current form data */
107
formData?: T;
108
/** Context object passed to all fields and widgets */
109
formContext?: F;
110
111
// Form configuration
112
/** Prefix for form field IDs (default: "root") */
113
idPrefix?: string;
114
/** Separator for nested field IDs (default: "_") */
115
idSeparator?: string;
116
/** Disable the entire form */
117
disabled?: boolean;
118
/** Make the entire form read-only */
119
readonly?: boolean;
120
121
// Registry overrides
122
/** Custom field components */
123
fields?: RegistryFieldsType<T, S, F>;
124
/** Custom widget components */
125
widgets?: RegistryWidgetsType<T, S, F>;
126
/** Custom template components */
127
templates?: Partial<TemplatesType<T, S, F>>;
128
129
// Event handlers
130
/** Called when form data changes */
131
onChange?: (data: IChangeEvent<T, S, F>, id?: string) => void;
132
/** Called when validation errors occur */
133
onError?: (errors: RJSFValidationError[]) => void;
134
/** Called when form is submitted */
135
onSubmit?: (data: IChangeEvent<T, S, F>, event: FormEvent<any>) => void;
136
/** Called when a field loses focus */
137
onBlur?: (id: string, data: any) => void;
138
/** Called when a field gains focus */
139
onFocus?: (id: string, data: any) => void;
140
141
// Validation configuration
142
/** Custom validation function */
143
customValidate?: CustomValidator<T, S, F>;
144
/** Additional errors to display */
145
extraErrors?: ErrorSchema<T>;
146
/** Whether extra errors should block form submission */
147
extraErrorsBlockSubmit?: boolean;
148
/** Disable HTML5 validation */
149
noHtml5Validate?: boolean;
150
/** Validate on every change (default: false) */
151
liveValidate?: boolean;
152
/** Omit extra data on change events */
153
liveOmit?: boolean;
154
/** Omit extra data on form submission */
155
omitExtraData?: boolean;
156
/** Where to show error list: false, 'top', or 'bottom' */
157
showErrorList?: false | 'top' | 'bottom';
158
/** Transform validation errors before display */
159
transformErrors?: ErrorTransformer<T, S, F>;
160
/** Auto-focus first field with error */
161
focusOnFirstError?: boolean | ((error: RJSFValidationError) => void);
162
163
// HTML form attributes
164
/** Accept-charset HTML attribute */
165
acceptCharset?: string;
166
/** Action HTML attribute */
167
action?: string;
168
/** Autocomplete HTML attribute */
169
autoComplete?: string;
170
/** CSS class name */
171
className?: string;
172
/** Enctype HTML attribute */
173
enctype?: string;
174
/** HTML id attribute */
175
id?: string;
176
/** HTML name attribute */
177
name?: string;
178
/** HTTP method */
179
method?: string;
180
/** Custom HTML tag (default: 'form') */
181
tagName?: ElementType;
182
/** Target HTML attribute */
183
target?: string;
184
185
// Advanced configuration
186
/** Translation function for internationalization */
187
translateString?: (str: TranslatableString, params?: string[]) => string;
188
/** Experimental default form state behavior */
189
experimental_defaultFormStateBehavior?: Experimental_DefaultFormStateBehavior;
190
/** Experimental custom allOf merger */
191
experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>;
192
193
// Other
194
/** Custom submit button or form content */
195
children?: ReactNode;
196
/** Internal form wrapper component */
197
_internalFormWrapper?: ElementType;
198
}
199
```
200
201
### Form State Interface
202
203
Interface representing the internal state of the Form component.
204
205
```typescript { .api }
206
interface FormState<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
207
/** Current form data */
208
formData: T;
209
/** Current validation errors */
210
errors: RJSFValidationError[];
211
/** Current error schema structure */
212
errorSchema: ErrorSchema<T>;
213
/** Schema-level validation errors */
214
schemaValidationErrors: RJSFValidationError[];
215
/** Schema-level error schema */
216
schemaValidationErrorSchema: ErrorSchema<T>;
217
}
218
```
219
220
### Change Event Interface
221
222
Interface for form change and submit events.
223
224
```typescript { .api }
225
interface IChangeEvent<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
226
/** Current schema */
227
schema: S;
228
/** Current UI schema */
229
uiSchema: UiSchema<T, S, F>;
230
/** Current ID schema */
231
idSchema: IdSchema<T>;
232
/** Schema utilities instance */
233
schemaUtils: SchemaUtilsType<T, S, F>;
234
/** Current form data */
235
formData?: T;
236
/** Whether form is in edit mode */
237
edit: boolean;
238
/** Current validation errors */
239
errors: RJSFValidationError[];
240
/** Current error schema */
241
errorSchema: ErrorSchema<T>;
242
/** Status when submitted (only present on submit) */
243
status?: 'submitted';
244
}
245
```
246
247
## Advanced Usage Patterns
248
249
### Form Refs and Imperative API
250
251
```typescript
252
import { useRef } from 'react';
253
import Form from '@rjsf/core';
254
255
const FormWithRef = () => {
256
const formRef = useRef<Form>(null);
257
258
const handleCustomSubmit = () => {
259
// Validate programmatically
260
if (formRef.current?.validateForm()) {
261
// Submit programmatically
262
formRef.current.submit();
263
}
264
};
265
266
const handleReset = () => {
267
formRef.current?.reset();
268
};
269
270
return (
271
<div>
272
<Form
273
ref={formRef}
274
schema={schema}
275
validator={validator}
276
onSubmit={handleSubmit}
277
/>
278
<button onClick={handleCustomSubmit}>Custom Submit</button>
279
<button onClick={handleReset}>Reset Form</button>
280
</div>
281
);
282
};
283
```
284
285
### Custom Validation
286
287
```typescript
288
const customValidate = (formData, errors, uiSchema) => {
289
// Cross-field validation
290
if (formData.password !== formData.confirmPassword) {
291
errors.confirmPassword.addError("Passwords don't match");
292
}
293
294
// Async validation
295
if (formData.email) {
296
validateEmailAsync(formData.email).then(isValid => {
297
if (!isValid) {
298
errors.email.addError("Email already exists");
299
}
300
});
301
}
302
303
return errors;
304
};
305
306
<Form
307
schema={schema}
308
validator={validator}
309
customValidate={customValidate}
310
liveValidate={true}
311
/>
312
```
313
314
### Form Context Usage
315
316
```typescript
317
const formContext = {
318
currentUser: user,
319
theme: 'dark',
320
readonlyMode: false
321
};
322
323
<Form
324
schema={schema}
325
validator={validator}
326
formContext={formContext}
327
// Form context is available in all custom fields/widgets
328
/>
329
```
330
331
### Error Handling and Transformation
332
333
```typescript
334
const transformErrors = (errors) => {
335
return errors.map(error => ({
336
...error,
337
message: translateError(error.message, currentLocale)
338
}));
339
};
340
341
<Form
342
schema={schema}
343
validator={validator}
344
transformErrors={transformErrors}
345
showErrorList="top"
346
focusOnFirstError={true}
347
/>
348
```