Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/custom template per field #4352

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ it according to semantic versioning. For example, if your PR adds a breaking cha
should change the heading of the (upcoming) version to include a major version bump.

-->
# 5.23.0

## @rjsf/utils

- Updated `getTemplate()` to allow per-field customization using string key from `Registry`, fixing [#3695](https://github.com/rjsf-team/react-jsonschema-form/issues/3695).
- 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)
- Updated tests to cover the new `getTemplate()` functionality

## Dev / docs / playground

- Updated `advanced-customization/custom-templates` with the new feature.

# 5.23.2

Expand Down
67 changes: 61 additions & 6 deletions packages/docs/docs/advanced-customization/custom-templates.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,27 @@ render(
);
```

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

```tsx
import { UiSchema } from '@rjsf/utils';
import ArrayFieldTemplate from './ArrayFieldTemplate';

const uiSchema: UiSchema = {
'ui:ArrayFieldTemplate': ArrayFieldTemplate,
};
```

or a string value from the `Registry` :

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

const uiSchema: UiSchema = {
'ui:ArrayFieldTemplate': 'CustomArrayFieldTemplate',
};
```

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.

The following props are passed to each `ArrayFieldTemplate`:
Expand Down Expand Up @@ -163,16 +174,27 @@ render(
);
```

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

```tsx
import { UiSchema } from '@rjsf/utils';
import ArrayFieldDescriptionTemplate from './ArrayFieldDescriptionTemplate';

const uiSchema: UiSchema = {
'ui:ArrayFieldDescriptionTemplate': ArrayFieldDescriptionTemplate,
};
```

or a string value from the `Registry` :

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

const uiSchema: UiSchema = {
'ui:ArrayFieldDescriptionTemplate': 'CustomArrayFieldDescriptionTemplate',
};
```

The following props are passed to each `ArrayFieldDescriptionTemplate`:

- `description`: The description of the array field being rendered.
Expand Down Expand Up @@ -261,13 +283,24 @@ render(
);
```

You also can provide your own template to a uiSchema by specifying a `ui:ArrayFieldDescriptionTemplate` property.
You also can provide your own template to a uiSchema by specifying a `ui:ArrayFieldDescriptionTemplate` property with your Component :

```tsx
import { UiSchema } from '@rjsf/utils';
import ArrayFieldDescriptionTemplate from './ArrayFieldDescriptionTemplate';

const uiSchema: UiSchema = {
'ui:ArrayFieldTitleTemplate': ArrayFieldTitleTemplate,
'ui:ArrayFieldDescriptionTemplate': ArrayFieldDescriptionTemplate,
};
```

or a string value from the `Registry` :

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

const uiSchema: UiSchema = {
'ui:ArrayFieldDescriptionTemplate': 'CustomArrayFieldDescriptionTemplate',
};
```

Expand Down Expand Up @@ -615,16 +648,27 @@ render(
);
```

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

```tsx
import { UiSchema } from '@rjsf/utils';
import CustomFieldTemplate from './CustomFieldTemplate';

const uiSchema: UiSchema = {
'ui:FieldTemplate': CustomFieldTemplate,
};
```

or a string value from the `Registry` :

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

const uiSchema: UiSchema = {
'ui:FieldTemplate': 'CustomFieldTemplate',
};
```

If you want to handle the rendering of each element yourself, you can use the props `rawHelp`, `rawDescription` and `rawErrors`.

The following props are passed to a custom field template component:
Expand Down Expand Up @@ -693,16 +737,27 @@ render(
);
```

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

```tsx
import { UiSchema } from '@rjsf/utils';
import ObjectFieldTemplate from './ObjectFieldTemplate';

const uiSchema: UiSchema = {
'ui:ObjectFieldTemplate': ObjectFieldTemplate,
};
```

or a string value from the `Registry` :

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

const uiSchema: UiSchema = {
'ui:ObjectFieldTemplate': 'ObjectFieldTemplate',
};
```

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.

The following props are passed to each `ObjectFieldTemplate` as defined by the `ObjectFieldTemplateProps` in `@rjsf/utils`:
Expand Down
11 changes: 11 additions & 0 deletions packages/utils/src/getTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ export default function getTemplate<
if (name === 'ButtonTemplates') {
return templates[name];
}
// Allow templates to be customized per-field by using string keys from the registry
if (
Object.hasOwn(uiOptions, name) &&
typeof uiOptions[name] === 'string' &&
Object.hasOwn(templates, uiOptions[name] as string)
) {
const key = uiOptions[name];
// Evaluating templates[key] results in TS2590: Expression produces a union type that is too complex to represent
// To avoid that, we cast templates to `any` before accessing the key field
return (templates as any)[key];
}
return (
// Evaluating uiOptions[name] results in TS2590: Expression produces a union type that is too complex to represent
// To avoid that, we cast uiOptions to `any` before accessing the name field
Expand Down
Loading
Loading