Skip to content

Commit bf49ef1

Browse files
lucasmchtLFRW2K\lecmil2heath-freenome
authored
Feat/custom template per field (#4352)
* [MISC] Retrieved change from older PR * [MISC] Updated documentation * [MISC] Updated types * [EVO] Added test for custom template name in registry * [FIX] Docx * [FIX] Templates typing * [MISC] Updated docs * [MISC] Moved type and removed blank lines * [FIX] Template type * FIX: Fixed tests * FIX getTemplate.test.ts * DOCS: Add section for custom templates in registry * FIX: Node 14 compat * Update types.ts * Update packages/utils/src/types.ts * Apply suggestions from code review * Apply suggestions from code review --------- Co-authored-by: LFRW2K\lecmil2 <[email protected]> Co-authored-by: Heath C <[email protected]>
1 parent 2a03293 commit bf49ef1

File tree

5 files changed

+219
-117
lines changed

5 files changed

+219
-117
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ should change the heading of the (upcoming) version to include a major version b
114114
- BREAKING CHANGE: Removed the deprecated `RJSF_ADDITONAL_PROPERTIES_FLAG` constant
115115
- Updated the `WrapIfAdditionalTemplateProps` to include `hideError` and `rawErrors` in support of moving `Bootstrap 3` marker classes out of `SchemaField`
116116
- Added support for `patternProperties` [#1944](https://github.com/rjsf-team/react-jsonschema-form/issues/1944)
117+
- Updated `getTemplate()` to allow per-field customization using string key from `Registry`, fixing [#3695](https://github.com/rjsf-team/react-jsonschema-form/issues/3695).
118+
- Updated `TemplatesType` to allow for a string key to be used to reference a custom template in the `Registry`, fixing [#3695](https://github.com/rjsf-team/react-jsonschema-form/issues/3695)
119+
- Updated tests to cover the new `getTemplate()` functionality
117120

118121
## @rjsf/validator-ajv6
119122

@@ -134,6 +137,7 @@ should change the heading of the (upcoming) version to include a major version b
134137
- Replaced Lerna with Nx, updated all lerna commands to use the Nx CLI
135138
- BREAKING CHANGE: Updated all `peerDependencies` to change minimal `React` support to `>=18`
136139
- Added documentation and playground example for `patternProperties`
140+
- Updated `advanced-customization/custom-templates` with the new feature.
137141

138142
# 6.0.0-alpha.0
139143

packages/docs/docs/advanced-customization/custom-templates.md

+78-6
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,27 @@ render(
7878
);
7979
```
8080

81-
You also can provide your own field template to a uiSchema by specifying a `ui:ArrayFieldTemplate` property.
81+
You also can provide your own field template to a uiSchema by specifying a `ui:ArrayFieldTemplate` property with your Component :
8282

8383
```tsx
8484
import { UiSchema } from '@rjsf/utils';
85+
import ArrayFieldTemplate from './ArrayFieldTemplate';
8586

8687
const uiSchema: UiSchema = {
8788
'ui:ArrayFieldTemplate': ArrayFieldTemplate,
8889
};
8990
```
9091

92+
or a string value from the `Registry` :
93+
94+
```tsx
95+
import { UiSchema } from '@rjsf/utils';
96+
97+
const uiSchema: UiSchema = {
98+
'ui:ArrayFieldTemplate': 'CustomArrayFieldTemplate',
99+
};
100+
```
101+
91102
Please see the [customArray.tsx sample](https://github.com/rjsf-team/react-jsonschema-form/blob/main/packages/playground/src/samples/customArray.tsx) from the [playground](https://rjsf-team.github.io/react-jsonschema-form/) for another example.
92103

93104
The following props are passed to each `ArrayFieldTemplate`:
@@ -165,16 +176,27 @@ render(
165176
);
166177
```
167178

168-
You also can provide your own template to a uiSchema by specifying a `ui:ArrayFieldDescriptionTemplate` property.
179+
You also can provide your own field template to a uiSchema by specifying a `ui:ArrayFieldDescriptionTemplate` property with your Component :
169180

170181
```tsx
171182
import { UiSchema } from '@rjsf/utils';
183+
import ArrayFieldDescriptionTemplate from './ArrayFieldDescriptionTemplate';
172184

173185
const uiSchema: UiSchema = {
174186
'ui:ArrayFieldDescriptionTemplate': ArrayFieldDescriptionTemplate,
175187
};
176188
```
177189

190+
or a string value from the `Registry` :
191+
192+
```tsx
193+
import { UiSchema } from '@rjsf/utils';
194+
195+
const uiSchema: UiSchema = {
196+
'ui:ArrayFieldDescriptionTemplate': 'CustomArrayFieldDescriptionTemplate',
197+
};
198+
```
199+
178200
The following props are passed to each `ArrayFieldDescriptionTemplate`:
179201

180202
- `description`: The description of the array field being rendered.
@@ -322,13 +344,24 @@ render(
322344
);
323345
```
324346

325-
You also can provide your own template to a uiSchema by specifying a `ui:ArrayFieldDescriptionTemplate` property.
347+
You also can provide your own template to a uiSchema by specifying a `ui:ArrayFieldDescriptionTemplate` property with your Component :
348+
349+
```tsx
350+
import { UiSchema } from '@rjsf/utils';
351+
import ArrayFieldDescriptionTemplate from './ArrayFieldDescriptionTemplate';
352+
353+
const uiSchema: UiSchema = {
354+
'ui:ArrayFieldDescriptionTemplate': ArrayFieldDescriptionTemplate,
355+
};
356+
```
357+
358+
or a string value from the `Registry` :
326359

327360
```tsx
328361
import { UiSchema } from '@rjsf/utils';
329362

330363
const uiSchema: UiSchema = {
331-
'ui:ArrayFieldTitleTemplate': ArrayFieldTitleTemplate,
364+
'ui:ArrayFieldDescriptionTemplate': 'CustomArrayFieldDescriptionTemplate',
332365
};
333366
```
334367

@@ -676,16 +709,27 @@ render(
676709
);
677710
```
678711

679-
You also can provide your own field template to a uiSchema by specifying a `ui:FieldTemplate` property.
712+
You also can provide your own field template to a uiSchema by specifying a `ui:FieldTemplate` property with your Component :
680713

681714
```tsx
682715
import { UiSchema } from '@rjsf/utils';
716+
import CustomFieldTemplate from './CustomFieldTemplate';
683717

684718
const uiSchema: UiSchema = {
685719
'ui:FieldTemplate': CustomFieldTemplate,
686720
};
687721
```
688722

723+
or a string value from the `Registry` :
724+
725+
```tsx
726+
import { UiSchema } from '@rjsf/utils';
727+
728+
const uiSchema: UiSchema = {
729+
'ui:FieldTemplate': 'CustomFieldTemplate',
730+
};
731+
```
732+
689733
If you want to handle the rendering of each element yourself, you can use the props `rawHelp`, `rawDescription` and `rawErrors`.
690734

691735
The following props are passed to a custom field template component:
@@ -789,16 +833,27 @@ render(
789833
);
790834
```
791835

792-
You also can provide your own field template to a uiSchema by specifying a `ui:ObjectFieldTemplate` property.
836+
You also can provide your own field template to a uiSchema by specifying a `ui:ObjectFieldTemplate` property with your Component :
793837

794838
```tsx
795839
import { UiSchema } from '@rjsf/utils';
840+
import ObjectFieldTemplate from './ObjectFieldTemplate';
796841

797842
const uiSchema: UiSchema = {
798843
'ui:ObjectFieldTemplate': ObjectFieldTemplate,
799844
};
800845
```
801846

847+
or a string value from the `Registry` :
848+
849+
```tsx
850+
import { UiSchema } from '@rjsf/utils';
851+
852+
const uiSchema: UiSchema = {
853+
'ui:ObjectFieldTemplate': 'ObjectFieldTemplate',
854+
};
855+
```
856+
802857
Please see the [customObject.tsx sample](https://github.com/rjsf-team/react-jsonschema-form/blob/main/packages/playground/src/samples/customObject.tsx) from the [playground](https://rjsf-team.github.io/react-jsonschema-form/) for a better example.
803858

804859
The following props are passed to each `ObjectFieldTemplate` as defined by the `ObjectFieldTemplateProps` in `@rjsf/utils`:
@@ -1145,3 +1200,20 @@ The following prop is passed to a `SubmitButton`:
11451200

11461201
- `uiSchema`: The uiSchema object for this field, used to extract the `UISchemaSubmitButtonOptions`.
11471202
- `registry`: The `registry` object.
1203+
1204+
## Custom Templates
1205+
1206+
You can now add custom components to the registry and reference them in your `uiSchema` using string keys.
1207+
1208+
### Adding Custom Templates to the Registry
1209+
1210+
```tsx
1211+
import CustomArrayFieldTemplate from './CustomArrayFieldTemplate';
1212+
import { UiSchema } from '@rjsf/utils';
1213+
1214+
// Add the custom template to the registry
1215+
const registry = { templates: { CustomArrayFieldTemplate } };
1216+
1217+
// Use the custom template in the uiSchema
1218+
const uiSchema: UiSchema = { 'ui:ArrayFieldTemplate': 'CustomArrayFieldTemplate' };
1219+
```

packages/utils/src/getTemplate.ts

+11
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,17 @@ export default function getTemplate<
1818
if (name === 'ButtonTemplates') {
1919
return templates[name];
2020
}
21+
// Allow templates to be customized per-field by using string keys from the registry
22+
if (
23+
Object.hasOwn(uiOptions, name) &&
24+
typeof uiOptions[name] === 'string' &&
25+
Object.hasOwn(templates, uiOptions[name] as string)
26+
) {
27+
const key = uiOptions[name];
28+
// Evaluating templates[key] results in TS2590: Expression produces a union type that is too complex to represent
29+
// To avoid that, we cast templates to `any` before accessing the key field
30+
return (templates as any)[key];
31+
}
2132
return (
2233
// Evaluating uiOptions[name] results in TS2590: Expression produces a union type that is too complex to represent
2334
// To avoid that, we cast uiOptions to `any` before accessing the name field

0 commit comments

Comments
 (0)