Skip to content

Commit

Permalink
Added ui:*Template properties (#1152)
Browse files Browse the repository at this point in the history
* LV: Added `ui:*Template` properties for the various templates. Fixed CRLF endings to LF to stop Husky complaining.

* Fixed typeo in test/FieldTemplate_test.js

* Added tests for overriding

* Update advanced-customization.md

* Update advanced-customization.md

* Update advanced-customization.md
  • Loading branch information
loganvolkers authored and epicfaace committed Jul 13, 2019
1 parent 3abba3e commit 310b8a5
Show file tree
Hide file tree
Showing 8 changed files with 394 additions and 124 deletions.
57 changes: 51 additions & 6 deletions docs/advanced-customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

_ | Custom Field | Custom Template | Custom Widget
--|---------- | ------------- | ----
What it does | Overrides all behaviour | Overrides just the layout | Overrides just the input box (not layout, labels, or help, or validation)
Usage | Global or per-field | Only global | Global or per-field
Global Example | `<Form fields={MyCustomFields} />` | `<Form ArrayFieldTemplate={ArrayFieldTemplate} />` | `<Form widgets={MyCustomWidgets} />`
Per-Field Example | `"ui:field": MyField` | N/A | `"ui:widget":MyWidget`
Documentation | [Field](#field-props) | [Field Template](#field-template) - [Array Template](#array-field-template) - [Object Template](#object-field-template) - [Error List Template](#error-list-template) | [Custom Widgets](#custom-widget-components)
**What it does** | Overrides all behaviour | Overrides just the layout (not behaviour) | Overrides just the input box (not layout, labels, or help, or validation)
**Usage** | Global or per-field | Global or per-field | Global or per-field
**Global Example** | `<Form fields={MyCustomField} />` | `<Form ArrayFieldTemplate={MyArrayTemplate} />` | `<Form widgets={MyCustomWidget} />`
**Per-Field Example** | `"ui:field": MyCustomField` | `"ui:ArrayFieldTemplate": MyArrayTemplate` | `"ui:widget":MyCustomWidget`
**Documentation** | [Field](#field-props) | [Field Template](#field-template) - [Array Template](#array-field-template) - [Object Template](#object-field-template) - [Error List Template](#error-list-template) | [Custom Widgets](#custom-widget-components)

### Field template

Expand Down Expand Up @@ -35,6 +35,19 @@ render((
), document.getElementById("app"));
```

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

```jsx
const uiSchema = {
"ui:FieldTemplate": CustomFieldTemplate
}

render((
<Form schema={schema}
uiSchema={uiSchema} />,
), document.getElementById("app"));
```

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 All @@ -59,7 +72,7 @@ The following props are passed to a custom field template component:
- `uiSchema`: The uiSchema object for this field.
- `formContext`: The `formContext` object that you passed to Form.

> Note: you can only define a single field template for a form. If you need many, it's probably time to look at [custom fields](#custom-field-components) instead.
> Note: you can only define a single global field template for a form, but you can set individual field templates per property using `"ui:FieldTemplate"`.
### Array Field Template

Expand All @@ -82,8 +95,22 @@ render((
), document.getElementById("app"));
```

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

```jsx
const uiSchema = {
"ui:ArrayFieldTemplate": ArrayFieldTemplate
}

render((
<Form schema={schema}
uiSchema={uiSchema} />,
), document.getElementById("app"));
```

Please see [customArray.js](https://github.com/mozilla-services/react-jsonschema-form/blob/master/playground/samples/customArray.js) for a better example.


The following props are passed to each `ArrayFieldTemplate`:

- `DescriptionField`: The `DescriptionField` from the registry (in case you wanted to utilize it)
Expand Down Expand Up @@ -117,6 +144,8 @@ The following props are part of each element in `items`:
- `onReorderClick: (index, newIndex) => (event) => void`: Returns a function that swaps the items at `index` with `newIndex`.
- `readonly`: A boolean value stating if the array item is read-only.

> Note: Array and object field templates are always rendered inside of the FieldTemplate. To fully customize an array field template, you may need to specify both `ui:FieldTemplate` and `ui:ArrayFieldTemplate`.
### Object Field Template

Similarly to the `FieldTemplate` you can use an `ObjectFieldTemplate` to customize how your
Expand All @@ -139,6 +168,19 @@ render((
), document.getElementById("app"));
```

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

```jsx
const uiSchema = {
"ui:ObjectFieldTemplate": ObjectFieldTemplate
}

render((
<Form schema={schema}
uiSchema={uiSchema} />,
), document.getElementById("app"));
```

Please see [customObject.js](https://github.com/mozilla-services/react-jsonschema-form/blob/master/playground/samples/customObject.js) for a better example.

The following props are passed to each `ObjectFieldTemplate`:
Expand All @@ -164,6 +206,9 @@ The following props are part of each element in `properties`:
- `disabled`: A boolean value stating if the object property is disabled.
- `readonly`: A boolean value stating if the property is read-only.

> Note: Array and object field templates are always rendered inside of the FieldTemplate. To fully customize an object field template, you may need to specify both `ui:FieldTemplate` and `ui:ObjectFieldTemplate`.

### Error List template

To take control over how the form errors are displayed, you can define an *error list template* for your form. This list is the form global error list that appears at the top of your forms.
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"build:lib": "rimraf lib && cross-env NODE_ENV=production babel -d lib/ src/",
"build:dist": "rimraf dist && cross-env NODE_ENV=production webpack --config webpack.config.dist.js",
"build:playground": "rimraf build && cross-env NODE_ENV=production webpack --config webpack.config.prod.js && cp playground/index.prod.html build/index.html",
"cs-check": "prettier -l $npm_package_prettierOptions '{playground,src,test}/**/*.js'",
"cs-format": "prettier --jsx-bracket-same-line --trailing-comma es5 --use-tabs false --semi --tab-width 2 '{playground,src,test}/**/*.js' --write",
"cs-check": "prettier -l $npm_package_prettierOptions \"{playground,src,test}/**/*.js\"",
"cs-format": "prettier --jsx-bracket-same-line --trailing-comma es5 --use-tabs false --semi --tab-width 2 \"{playground,src,test}/**/*.js\" --write",
"dist": "npm run build:lib && npm run build:dist",
"lint": "eslint src test playground",
"prepare": "npm run dist",
Expand Down
10 changes: 8 additions & 2 deletions src/components/fields/ArrayField.js
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,10 @@ class ArrayField extends Component {
};

// Check if a custom render function was passed in
const Component = ArrayFieldTemplate || DefaultNormalArrayFieldTemplate;
const Component =
uiSchema["ui:ArrayFieldTemplate"] ||
ArrayFieldTemplate ||
DefaultNormalArrayFieldTemplate;
return <Component {...arrayProps} />;
}

Expand Down Expand Up @@ -670,7 +673,10 @@ class ArrayField extends Component {
};

// Check if a custom template template was passed in
const Template = ArrayFieldTemplate || DefaultFixedArrayFieldTemplate;
const Template =
uiSchema["ui:ArrayFieldTemplate"] ||
ArrayFieldTemplate ||
DefaultFixedArrayFieldTemplate;
return <Template {...arrayProps} />;
}

Expand Down
6 changes: 5 additions & 1 deletion src/components/fields/ObjectField.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,11 @@ class ObjectField extends Component {
);
}

const Template = registry.ObjectFieldTemplate || DefaultObjectFieldTemplate;
const Template =
uiSchema["ui:ObjectFieldTemplate"] ||
registry.ObjectFieldTemplate ||
DefaultObjectFieldTemplate;

const templateProps = {
title: uiSchema["ui:title"] || title,
description,
Expand Down
9 changes: 3 additions & 6 deletions src/components/fields/SchemaField.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,12 +236,9 @@ function SchemaFieldRender(props) {
required,
registry = getDefaultRegistry(),
} = props;
const {
definitions,
fields,
formContext,
FieldTemplate = DefaultTemplate,
} = registry;
const { definitions, fields, formContext } = registry;
const FieldTemplate =
uiSchema["ui:FieldTemplate"] || registry.FieldTemplate || DefaultTemplate;
let idSchema = props.idSchema;
const schema = retrieveSchema(props.schema, definitions, formData);
idSchema = mergeObjects(
Expand Down
Loading

0 comments on commit 310b8a5

Please sign in to comment.