From 310b8a5309bd55fd1c3e1533c93b3ce135b03dda Mon Sep 17 00:00:00 2001 From: Logan Volkers Date: Sat, 13 Jul 2019 10:56:24 -0700 Subject: [PATCH] Added `ui:*Template` properties (#1152) * 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 --- docs/advanced-customization.md | 57 +++++- package.json | 4 +- src/components/fields/ArrayField.js | 10 +- src/components/fields/ObjectField.js | 6 +- src/components/fields/SchemaField.js | 9 +- test/ArrayFieldTemplate_test.js | 277 ++++++++++++++++++++------- test/FieldTemplate_test.js | 64 +++++-- test/ObjectFieldTemplate_test.js | 91 ++++++--- 8 files changed, 394 insertions(+), 124 deletions(-) diff --git a/docs/advanced-customization.md b/docs/advanced-customization.md index f72613255d..ce0e7c44b9 100644 --- a/docs/advanced-customization.md +++ b/docs/advanced-customization.md @@ -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 | `
` | `` | `` -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** | `` | `` | `` +**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 @@ -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(( + , +), 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: @@ -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 @@ -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(( + , +), 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) @@ -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 @@ -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(( + , +), 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`: @@ -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. diff --git a/package.json b/package.json index ca28d0ec5c..320767512d 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/components/fields/ArrayField.js b/src/components/fields/ArrayField.js index c15b3d768b..7863b94a88 100644 --- a/src/components/fields/ArrayField.js +++ b/src/components/fields/ArrayField.js @@ -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 ; } @@ -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