0
# Template Components
1
2
Template components control how form elements are displayed and styled. They provide the layout structure, styling, and presentation logic for fields, errors, arrays, buttons, and other form elements.
3
4
## Capabilities
5
6
### Template Component Types
7
8
Built-in template components that control form layout and presentation.
9
10
```typescript { .api }
11
interface TemplatesType<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
12
/** Template for array field descriptions */
13
ArrayFieldDescriptionTemplate: ComponentType<ArrayFieldDescriptionProps<T, S, F>>;
14
/** Template for individual array items with controls */
15
ArrayFieldItemTemplate: ComponentType<ArrayFieldTemplateItemType<T, S, F>>;
16
/** Template for entire array fields with add/remove controls */
17
ArrayFieldTemplate: ComponentType<ArrayFieldTemplateProps<T, S, F>>;
18
/** Template for array field titles and headers */
19
ArrayFieldTitleTemplate: ComponentType<ArrayFieldTitleProps<T, S, F>>;
20
/** Base template for input widgets with common styling */
21
BaseInputTemplate: ComponentType<BaseInputTemplateProps<T, S, F>>;
22
/** Template for field descriptions and help text */
23
DescriptionFieldTemplate: ComponentType<DescriptionFieldProps<T, S, F>>;
24
/** Template for error list display at form level */
25
ErrorListTemplate: ComponentType<ErrorListProps<T, S, F>>;
26
/** Template for individual form fields with labels and errors */
27
FieldTemplate: ComponentType<FieldTemplateProps<T, S, F>>;
28
/** Template for field-specific error messages */
29
FieldErrorTemplate: ComponentType<FieldErrorProps<T, S, F>>;
30
/** Template for field help text display */
31
FieldHelpTemplate: ComponentType<FieldHelpProps<T, S, F>>;
32
/** Template for object fields with property layout */
33
ObjectFieldTemplate: ComponentType<ObjectFieldTemplateProps<T, S, F>>;
34
/** Template for field titles and labels */
35
TitleFieldTemplate: ComponentType<TitleFieldProps<T, S, F>>;
36
/** Template for unsupported field types fallback */
37
UnsupportedFieldTemplate: ComponentType<UnsupportedFieldProps<T, S, F>>;
38
/** Template for additional properties wrapper */
39
WrapIfAdditionalTemplate: ComponentType<WrapIfAdditionalTemplateProps<T, S, F>>;
40
/** Collection of button templates for form actions */
41
ButtonTemplates: {
42
/** Form submit button */
43
SubmitButton: ComponentType<SubmitButtonProps<T, S, F>>;
44
/** Add array item button */
45
AddButton: ComponentType<IconButtonProps<T, S, F>>;
46
/** Copy array item button */
47
CopyButton: ComponentType<IconButtonProps<T, S, F>>;
48
/** Move array item down button */
49
MoveDownButton: ComponentType<IconButtonProps<T, S, F>>;
50
/** Move array item up button */
51
MoveUpButton: ComponentType<IconButtonProps<T, S, F>>;
52
/** Remove array item button */
53
RemoveButton: ComponentType<IconButtonProps<T, S, F>>;
54
};
55
}
56
```
57
58
## Field Layout Templates
59
60
### FieldTemplate
61
62
Main template for individual form fields, controls layout of labels, inputs, errors, and help text.
63
64
```typescript { .api }
65
/**
66
* Main template for individual form fields
67
* Handles label, input, error, and help text layout
68
*/
69
interface FieldTemplateProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
70
/** Field ID for accessibility */
71
id: string;
72
/** CSS class names */
73
classNames: string;
74
/** Field label text */
75
label?: string;
76
/** Whether to display the label */
77
displayLabel: boolean;
78
/** Field description text */
79
description?: React.ReactNode;
80
/** Raw description from schema */
81
rawDescription?: string;
82
/** Field help text */
83
help?: React.ReactNode;
84
/** Raw help text */
85
rawHelp?: string;
86
/** Field error messages */
87
errors?: React.ReactNode;
88
/** Raw error messages */
89
rawErrors?: string[];
90
/** Whether field is required */
91
required: boolean;
92
/** Whether field is hidden */
93
hidden: boolean;
94
/** Whether field is readonly */
95
readonly: boolean;
96
/** Whether field is disabled */
97
disabled: boolean;
98
/** Form registry */
99
registry: Registry<T, S, F>;
100
/** Form context */
101
formContext: F;
102
/** Field children (widget) */
103
children: React.ReactNode;
104
/** JSON schema */
105
schema: S;
106
/** UI schema */
107
uiSchema: UiSchema<T, S, F>;
108
/** Form data */
109
formData: T;
110
}
111
112
const FieldTemplate: ComponentType<FieldTemplateProps<T, S, F>>;
113
```
114
115
**Usage Examples:**
116
117
```typescript
118
// Custom field template with Bootstrap styling
119
const BootstrapFieldTemplate = (props: FieldTemplateProps) => {
120
const {
121
id,
122
classNames,
123
label,
124
children,
125
errors,
126
help,
127
description,
128
hidden,
129
required,
130
displayLabel,
131
} = props;
132
133
if (hidden) {
134
return <div className="hidden">{children}</div>;
135
}
136
137
return (
138
<div className={`form-group ${classNames}`}>
139
{displayLabel && label && (
140
<label htmlFor={id} className="control-label">
141
{label}
142
{required && <span className="text-danger"> *</span>}
143
</label>
144
)}
145
{description && (
146
<div className="field-description text-muted">{description}</div>
147
)}
148
{children}
149
{errors && <div className="text-danger">{errors}</div>}
150
{help && <small className="form-text text-muted">{help}</small>}
151
</div>
152
);
153
};
154
```
155
156
### ObjectFieldTemplate
157
158
Template for object fields that contain multiple properties.
159
160
```typescript { .api }
161
/**
162
* Template for object fields with multiple properties
163
* Handles property layout and additional properties
164
*/
165
interface ObjectFieldTemplateProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
166
/** Object field ID */
167
id: string;
168
/** CSS class names */
169
classNames: string;
170
/** Object field title */
171
title?: string;
172
/** Object field description */
173
description?: React.ReactNode;
174
/** Whether title should be displayed */
175
displayTitle: boolean;
176
/** Array of property elements */
177
properties: ObjectFieldTemplatePropertyType[];
178
/** Whether object is required */
179
required: boolean;
180
/** Whether object is readonly */
181
readonly: boolean;
182
/** Whether object is disabled */
183
disabled: boolean;
184
/** Form registry */
185
registry: Registry<T, S, F>;
186
/** Form context */
187
formContext: F;
188
/** JSON schema */
189
schema: S;
190
/** UI schema */
191
uiSchema: UiSchema<T, S, F>;
192
/** Form data */
193
formData: T;
194
}
195
196
interface ObjectFieldTemplatePropertyType {
197
content: React.ReactElement;
198
name: string;
199
readonly: boolean;
200
disabled: boolean;
201
required: boolean;
202
}
203
204
const ObjectFieldTemplate: ComponentType<ObjectFieldTemplateProps<T, S, F>>;
205
```
206
207
**Custom Implementation:**
208
209
```typescript
210
const CustomObjectFieldTemplate = (props: ObjectFieldTemplateProps) => {
211
const { title, properties, description, displayTitle } = props;
212
213
return (
214
<fieldset className="object-field">
215
{displayTitle && title && <legend>{title}</legend>}
216
{description && <div className="object-description">{description}</div>}
217
<div className="object-properties">
218
{properties.map((prop, index) => (
219
<div key={index} className={`property ${prop.name}`}>
220
{prop.content}
221
</div>
222
))}
223
</div>
224
</fieldset>
225
);
226
};
227
```
228
229
### BaseInputTemplate
230
231
Base template for input widgets with common styling and structure.
232
233
```typescript { .api }
234
/**
235
* Base template for input widgets
236
* Provides common structure for form inputs
237
*/
238
interface BaseInputTemplateProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
239
/** Input ID */
240
id: string;
241
/** Input value */
242
value: any;
243
/** Input label */
244
label: string;
245
/** Input type */
246
type: string;
247
/** Placeholder text */
248
placeholder?: string;
249
/** Whether input is required */
250
required: boolean;
251
/** Whether input is disabled */
252
disabled: boolean;
253
/** Whether input is readonly */
254
readonly: boolean;
255
/** Whether input should autofocus */
256
autofocus: boolean;
257
/** Change handler */
258
onChange: (value: any) => void;
259
/** Blur handler */
260
onBlur: (id: string, value: any) => void;
261
/** Focus handler */
262
onFocus: (id: string, value: any) => void;
263
/** Additional options */
264
options: any;
265
/** JSON schema */
266
schema: S;
267
/** UI schema */
268
uiSchema: UiSchema<T, S, F>;
269
/** Form context */
270
formContext: F;
271
/** Form registry */
272
registry: Registry<T, S, F>;
273
/** Raw validation errors */
274
rawErrors?: string[];
275
}
276
277
const BaseInputTemplate: ComponentType<BaseInputTemplateProps<T, S, F>>;
278
```
279
280
## Array Templates
281
282
### ArrayFieldTemplate
283
284
Main template for array fields with item management controls.
285
286
```typescript { .api }
287
/**
288
* Template for array fields with add/remove/reorder controls
289
* Manages array items and provides action buttons
290
*/
291
interface ArrayFieldTemplateProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
292
/** Array field ID */
293
id: string;
294
/** CSS class names */
295
classNames: string;
296
/** Array field title */
297
title?: string;
298
/** Array field description */
299
description?: React.ReactNode;
300
/** Array items */
301
items: ArrayFieldTemplateItemType<T, S, F>[];
302
/** Whether items can be added */
303
canAdd: boolean;
304
/** Add item handler */
305
onAddClick: (event: React.MouseEvent) => void;
306
/** Whether array is disabled */
307
disabled: boolean;
308
/** Whether array is readonly */
309
readonly: boolean;
310
/** Form registry */
311
registry: Registry<T, S, F>;
312
/** Form context */
313
formContext: F;
314
/** JSON schema */
315
schema: S;
316
/** UI schema */
317
uiSchema: UiSchema<T, S, F>;
318
/** Form data */
319
formData: T[];
320
}
321
322
interface ArrayFieldTemplateItemType<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
323
/** Item content */
324
children: React.ReactElement;
325
/** Item index */
326
index: number;
327
/** Whether item can be removed */
328
hasRemove: boolean;
329
/** Whether item can be moved up */
330
hasMoveUp: boolean;
331
/** Whether item can be moved down */
332
hasMoveDown: boolean;
333
/** Whether item can be copied */
334
hasCopy: boolean;
335
/** Remove item handler */
336
onDropIndexClick: (index: number) => (event: React.MouseEvent) => void;
337
/** Move up handler */
338
onReorderClick: (index: number, newIndex: number) => (event: React.MouseEvent) => void;
339
/** Copy item handler */
340
onCopyIndexClick: (index: number) => (event: React.MouseEvent) => void;
341
/** Whether item is readonly */
342
readonly: boolean;
343
/** Whether item is disabled */
344
disabled: boolean;
345
}
346
347
const ArrayFieldTemplate: ComponentType<ArrayFieldTemplateProps<T, S, F>>;
348
```
349
350
**Custom Array Template:**
351
352
```typescript
353
const CustomArrayFieldTemplate = (props: ArrayFieldTemplateProps) => {
354
const {
355
items,
356
canAdd,
357
onAddClick,
358
title,
359
description,
360
registry
361
} = props;
362
363
const { AddButton } = registry.templates.ButtonTemplates;
364
365
return (
366
<div className="array-field">
367
{title && <h3>{title}</h3>}
368
{description && <div className="array-description">{description}</div>}
369
370
<div className="array-items">
371
{items.map((item, index) => (
372
<div key={index} className="array-item">
373
<div className="item-content">{item.children}</div>
374
<div className="item-controls">
375
{item.hasRemove && (
376
<button onClick={item.onDropIndexClick(item.index)}>
377
Remove
378
</button>
379
)}
380
{item.hasMoveUp && (
381
<button onClick={item.onReorderClick(item.index, item.index - 1)}>
382
Move Up
383
</button>
384
)}
385
{item.hasMoveDown && (
386
<button onClick={item.onReorderClick(item.index, item.index + 1)}>
387
Move Down
388
</button>
389
)}
390
</div>
391
</div>
392
))}
393
</div>
394
395
{canAdd && (
396
<div className="array-add">
397
<AddButton onClick={onAddClick} />
398
</div>
399
)}
400
</div>
401
);
402
};
403
```
404
405
### ArrayFieldItemTemplate
406
407
Template for individual array items with controls.
408
409
```typescript { .api }
410
/**
411
* Template for individual array items
412
* Wraps item content with controls
413
*/
414
const ArrayFieldItemTemplate: ComponentType<ArrayFieldTemplateItemType<T, S, F>>;
415
```
416
417
## Error and Help Templates
418
419
### ErrorListTemplate
420
421
Template for displaying form-level errors.
422
423
```typescript { .api }
424
/**
425
* Template for form-level error list display
426
* Shows validation errors at top or bottom of form
427
*/
428
interface ErrorListProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
429
/** Array of validation errors */
430
errors: RJSFValidationError[];
431
/** Form registry */
432
registry: Registry<T, S, F>;
433
/** Form context */
434
formContext: F;
435
/** JSON schema */
436
schema: S;
437
/** UI schema */
438
uiSchema: UiSchema<T, S, F>;
439
}
440
441
const ErrorListTemplate: ComponentType<ErrorListProps<T, S, F>>;
442
```
443
444
### FieldErrorTemplate
445
446
Template for field-specific error messages.
447
448
```typescript { .api }
449
/**
450
* Template for field-specific error messages
451
* Displays errors inline with fields
452
*/
453
interface FieldErrorProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
454
/** Array of error messages */
455
errors: string[];
456
/** Field ID */
457
idSchema: IdSchema<T>;
458
/** JSON schema */
459
schema: S;
460
/** UI schema */
461
uiSchema: UiSchema<T, S, F>;
462
/** Form registry */
463
registry: Registry<T, S, F>;
464
}
465
466
const FieldErrorTemplate: ComponentType<FieldErrorProps<T, S, F>>;
467
```
468
469
### FieldHelpTemplate
470
471
Template for field help text display.
472
473
```typescript { .api }
474
/**
475
* Template for field help text display
476
* Shows guidance and instructions for fields
477
*/
478
interface FieldHelpProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
479
/** Help text content */
480
help: React.ReactNode;
481
/** Field ID */
482
idSchema: IdSchema<T>;
483
/** JSON schema */
484
schema: S;
485
/** UI schema */
486
uiSchema: UiSchema<T, S, F>;
487
/** Form registry */
488
registry: Registry<T, S, F>;
489
}
490
491
const FieldHelpTemplate: ComponentType<FieldHelpProps<T, S, F>>;
492
```
493
494
## Button Templates
495
496
### Button Template Types
497
498
Collection of button templates for form actions.
499
500
```typescript { .api }
501
interface ButtonTemplates<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
502
/** Form submit button */
503
SubmitButton: ComponentType<SubmitButtonProps<T, S, F>>;
504
/** Add array item button */
505
AddButton: ComponentType<IconButtonProps<T, S, F>>;
506
/** Copy array item button */
507
CopyButton: ComponentType<IconButtonProps<T, S, F>>;
508
/** Move array item down button */
509
MoveDownButton: ComponentType<IconButtonProps<T, S, F>>;
510
/** Move array item up button */
511
MoveUpButton: ComponentType<IconButtonProps<T, S, F>>;
512
/** Remove array item button */
513
RemoveButton: ComponentType<IconButtonProps<T, S, F>>;
514
}
515
```
516
517
### SubmitButton
518
519
Template for form submit button.
520
521
```typescript { .api }
522
/**
523
* Template for form submit button
524
* Handles form submission trigger
525
*/
526
interface SubmitButtonProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
527
/** UI schema submit button options */
528
uiSchema: UiSchema<T, S, F>;
529
/** Form registry */
530
registry: Registry<T, S, F>;
531
/** Form context */
532
formContext: F;
533
/** Whether form is disabled */
534
disabled: boolean;
535
/** Whether form is readonly */
536
readonly: boolean;
537
}
538
539
const SubmitButton: ComponentType<SubmitButtonProps<T, S, F>>;
540
```
541
542
### Icon Button Props
543
544
Common props for array action buttons.
545
546
```typescript { .api }
547
interface IconButtonProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
548
/** Button icon name or element */
549
icon?: string | React.ReactElement;
550
/** Button color scheme */
551
color?: string;
552
/** Button title/tooltip */
553
title?: string;
554
/** CSS class names */
555
className?: string;
556
/** Tab index */
557
tabIndex?: number;
558
/** Whether button is disabled */
559
disabled?: boolean;
560
/** Click handler */
561
onClick?: (event: React.MouseEvent) => void;
562
/** UI schema */
563
uiSchema?: UiSchema<T, S, F>;
564
/** Form registry */
565
registry?: Registry<T, S, F>;
566
}
567
```
568
569
## Custom Template Implementation
570
571
### Custom Field Template
572
573
```typescript
574
const MaterialFieldTemplate = (props: FieldTemplateProps) => {
575
const {
576
id,
577
label,
578
children,
579
errors,
580
help,
581
description,
582
required,
583
displayLabel,
584
hidden
585
} = props;
586
587
if (hidden) {
588
return <div style={{ display: 'none' }}>{children}</div>;
589
}
590
591
return (
592
<div className="material-field">
593
{displayLabel && label && (
594
<label htmlFor={id} className="material-label">
595
{label}
596
{required && <span className="required">*</span>}
597
</label>
598
)}
599
600
<div className="material-input-container">
601
{children}
602
</div>
603
604
{description && (
605
<div className="material-description">{description}</div>
606
)}
607
608
{errors && (
609
<div className="material-errors">{errors}</div>
610
)}
611
612
{help && (
613
<div className="material-help">{help}</div>
614
)}
615
</div>
616
);
617
};
618
```
619
620
### Custom Button Templates
621
622
```typescript
623
const CustomButtonTemplates = {
624
SubmitButton: (props: SubmitButtonProps) => (
625
<button type="submit" className="btn btn-primary">
626
Submit Form
627
</button>
628
),
629
630
AddButton: (props: IconButtonProps) => (
631
<button
632
type="button"
633
className="btn btn-success btn-sm"
634
onClick={props.onClick}
635
disabled={props.disabled}
636
title="Add Item"
637
>
638
+ Add
639
</button>
640
),
641
642
RemoveButton: (props: IconButtonProps) => (
643
<button
644
type="button"
645
className="btn btn-danger btn-sm"
646
onClick={props.onClick}
647
disabled={props.disabled}
648
title="Remove Item"
649
>
650
× Remove
651
</button>
652
)
653
};
654
655
// Use custom templates
656
const customTemplates = {
657
FieldTemplate: MaterialFieldTemplate,
658
ButtonTemplates: CustomButtonTemplates
659
};
660
661
<Form
662
schema={schema}
663
validator={validator}
664
templates={customTemplates}
665
/>
666
```