From dba4ff42238d45cffdc300552b53820d34d4888b Mon Sep 17 00:00:00 2001 From: Francois Zaninotto Date: Mon, 16 Dec 2019 15:36:14 +0100 Subject: [PATCH 1/2] Improve Form customization documentation Refs #4156 --- docs/CreateEdit.md | 99 ++++++++++++++++++++++++++++++++++++++++++---- docs/Fields.md | 3 ++ docs/Inputs.md | 2 + 3 files changed, 96 insertions(+), 8 deletions(-) diff --git a/docs/CreateEdit.md b/docs/CreateEdit.md index 7ca737c9059..ef04771da26 100644 --- a/docs/CreateEdit.md +++ b/docs/CreateEdit.md @@ -381,14 +381,14 @@ React-admin provides guessers for the `List` view (`ListGuesser`), the `Edit` vi The `` component receives the `record` as prop from its parent component. It is responsible for rendering the actual form. It is also responsible for validating the form data. Finally, it receives a `handleSubmit` function as prop, to be called with the updated record as argument when the user submits the form. -The `` renders its child components line by line (within `
` components). It uses `react-final-form`. +The `` renders its child components line by line (within `
` components). It accepts Input and Field components as children. It relies on `react-final-form` for form handling. ![post edition form](./img/post-edition.png) By default the `` submits the form when the user presses `ENTER`. If you want to change this behaviour you can pass `false` for the `submitOnEnter` property, and the user will only be able to submit by pressing the save button. This can be useful e.g. if you have an input widget using `ENTER` for a special function. -Here are all the props accepted by the `` component: +Here are all the props you can set on the `` component: * [`initialValues`](#default-values) * [`validate`](#validation) @@ -397,8 +397,6 @@ Here are all the props accepted by the `` component: * [`toolbar`](#toolbar) * [`variant`](#variant) * [`margin`](#margin) -* `save`: The function invoked when the form is submitted. This is passed automatically by `react-admin` when the form component is used inside `Create` and `Edit` components. -* `saving`: A boolean indicating whether a save operation is ongoing. This is passed automatically by `react-admin` when the form component is used inside `Create` and `Edit` components. ```jsx export const PostCreate = (props) => ( @@ -412,6 +410,11 @@ export const PostCreate = (props) => ( ); ``` +**Tip**: `Create` and `Edit` inject more props to their child. So `SimpleForm` also expects these props to be set (but you shouldn't set them yourself): + +* `save`: The function invoked when the form is submitted. +* `saving`: A boolean indicating whether a save operation is ongoing. + ## The `` component Just like ``, `` receives the `record` prop, renders the actual form, and handles form validation on submit. However, the `` component renders inputs grouped by tab. The tabs are set by using `` components, which expect a `label` and an `icon` prop. @@ -884,7 +887,21 @@ Here are the props received by the `Toolbar` component when passed as the `toolb **Tip**: To alter the form values before submitting, you should use the `handleSubmit` prop. See [Altering the Form Values before Submitting](#altering-the-form-values-before-submitting) for more information and examples. -## Variant +## Customizing The Form Layout + +You can customize each row in a `` or in a `` by passing props to the Input components: + +* `className` +* [`variant`](#variant) +* [`margin`](#margin) +* [`formClassName`](#formClassName) +* [`fullWidth`](#fullWidth) + +You can find more about these props in [the Input documentation](./Inputs.md#common-input-props). + +You can also [wrap inputs inside containers](#custom-row-container), or [create a custom Form component](#custom-form-component), alternative to `` or ``. + +### Variant By default, react-admin input components use the Material Design "filled" variant. If you want to use the "standard" or "outlined" variants, you can either set the `variant` prop on each Input component individually, or set the `variant` prop directly on the Form component. In that case, the Form component will transmit the `variant` to each Input. @@ -915,7 +932,7 @@ export const PostEdit = (props) => ( ); ``` -## Margin +### Margin By default, react-admin input components use the Material Design "dense" margin. If you want to use the "normal" or "none" margins, you can either set the `margin` prop on each Input component individually, or set the `margin` prop directly on the Form component. In that case, the Form component will transmit the `margin` to each Input. @@ -929,7 +946,7 @@ export const PostEdit = (props) => ( ); ``` -## Customizing Input Container Styles +### `formClassName` The input components are wrapped inside a `div` to ensure a good looking form by default. You can pass a `formClassName` prop to the input components to customize the style of this `div`. For example, here is how to display two inputs on the same line: @@ -953,7 +970,73 @@ export const UserEdit = props => { } ``` -## Customizing The Form Layout +### `fullWidth` + +If you just need a form row to take the entire form width, use the `fullWidth` prop instead: + +```jsx +const useStyles = makeStyles({ + inlineBlock: { display: 'inline-flex', marginRight: '1rem' }, +}); + +export const UserEdit = props => { + const classes = useStyles(); + return ( + + + + + + + + ) +} +``` + +### Custom Row Container + +You may want to customize the styles of Input components by wrapping them inside a container with a custom style. Unfortunately, this doesn't work: + +```jsx +export const PostCreate = (props) => ( + + + {/* this does not work */} +
+ +
+ + +
+
+); +``` + +That's because `` clones its children and injects props to them (like `record` or `resource`). Input and Field components expect these props, but DOM elements don't. That means that if you wrap an Input or a Field element in a `
`, you'll get a React warning about unrecognized DOM attributes, and an error about missing props in the child. + +You can try passing `className` to the Input element directly - all form inputs accept a `className` prop. + +Alternatively, you can create a custom Input component: + +```jsx +const MyTextInput = props => ( +
+ +
+) +export const PostCreate = (props) => ( + + + {/* this works */} + + + + + +); +``` + +### Custom Form Component The `` and `` layouts are quite simple. In order to better use the screen real estate, you may want to arrange inputs differently, e.g. putting them in groups, adding separators, etc. For that purpose, you need to write a custom form layout, and use it instead of ``. diff --git a/docs/Fields.md b/docs/Fields.md index 2e8439df098..68f8cc903ca 100644 --- a/docs/Fields.md +++ b/docs/Fields.md @@ -23,6 +23,8 @@ export const PostList = (props) => ( ); ``` +## Common Field Props + All field components accept the following attributes: * `source`: Property name of your entity to view/edit. This attribute is required. @@ -31,6 +33,7 @@ All field components accept the following attributes: * `className`: A class name (usually generated by JSS) to customize the look and feel of the field element itself * `cellClassName`: A class name (usually generated by JSS) to customize the look and feel of the field container (e.g. the `` in a `Datagrid`). * `headerClassName`: A class name (usually generated by JSS) to customize the look and feel of the field header (e.g. the `` in a `Datagrid`). +* `formClassName`: A class name (usually generated by JSS) to customize the look and feel of the field container when it is used inside `` or ``. * `addLabel`: Defines the visibility of the label when the field is not in a `Datagrid`. Default value is `true`. * `textAlign`: Defines the text alignment inside a cell. Supports `left` (the default) and `right`. diff --git a/docs/Inputs.md b/docs/Inputs.md index 297d84b2ebc..1718b5041cf 100644 --- a/docs/Inputs.md +++ b/docs/Inputs.md @@ -34,6 +34,8 @@ All input components accept the following props: * `label`: Used as input label. Defaults to the humanized `source` when omitted. * `validate`: Validation rules for the current property. See the [Validation Documentation](./CreateEdit.md#validation) for details. * `helperText`: Text to be displayed under the input. +* `className`: A class name (usually generated by JSS) to customize the look and feel of the input element itself +* `formClassName`: Class name to be applied to the container of the input (e.g. the `
` forming each row in ``) * `fullWidth`: If `true`, the input will expand to fill the form width. Defaults to `false`. ```jsx From 2c945800e8ca5cb57199f71a8a1c727f65e788ab Mon Sep 17 00:00:00 2001 From: Francois Zaninotto Date: Mon, 16 Dec 2019 22:04:26 +0100 Subject: [PATCH 2/2] review --- docs/CreateEdit.md | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/docs/CreateEdit.md b/docs/CreateEdit.md index ef04771da26..ae8c97b4fba 100644 --- a/docs/CreateEdit.md +++ b/docs/CreateEdit.md @@ -975,22 +975,15 @@ export const UserEdit = props => { If you just need a form row to take the entire form width, use the `fullWidth` prop instead: ```jsx -const useStyles = makeStyles({ - inlineBlock: { display: 'inline-flex', marginRight: '1rem' }, -}); - -export const UserEdit = props => { - const classes = useStyles(); - return ( - - - - - - - - ) -} +export const UserEdit = props => ( + + + + + + + +); ``` ### Custom Row Container @@ -998,7 +991,7 @@ export const UserEdit = props => { You may want to customize the styles of Input components by wrapping them inside a container with a custom style. Unfortunately, this doesn't work: ```jsx -export const PostCreate = (props) => ( +export const PostCreate = props => ( {/* this does not work */}