Skip to content

Commit

Permalink
Merge pull request #4621 from WiXSL/fix-docs-button-sanitation
Browse files Browse the repository at this point in the history
[Docs]: Improve buttons sanitation explanation.
  • Loading branch information
fzaninotto authored Apr 7, 2020
2 parents a8db848 + 7b12716 commit 1dc5ca6
Showing 1 changed file with 23 additions and 18 deletions.
41 changes: 23 additions & 18 deletions docs/CreateEdit.md
Original file line number Diff line number Diff line change
Expand Up @@ -1057,10 +1057,15 @@ 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.
**Tip**: If you want to include a `<CreateButton>` in the `<Toolbar>`, the props injected by `<Toolbar>` to its children (`handleSubmit`, `handleSubmitWithRedirect`, `onSave`, `invalid`, `pristine`, `saving`, and `submitOnEnter`) will cause React warnings. You'll need to wrap `<CreateButton>` in another component and ignore the injected props, as follows:
**Tip**: If you want to include a custom `Button` in a `<Toolbar>` that doesn't render a react-admin `<Button>`, the props injected by `<Toolbar>` to its children (`handleSubmit`, `handleSubmitWithRedirect`, `onSave`, `invalid`, `pristine`, `saving`, and `submitOnEnter`) will cause React warnings. You'll need to wrap your custom `Button` in another component and ignore the injected props, as follows:
```jsx
const ToolbarCreateButton = ({
import React from 'react';
import Button from '@material-ui/core/Button';

const CustomButton = props => <Button label="My Custom Button" {...props} />

const ToolbarCustomButton = ({
handleSubmit,
handleSubmitWithRedirect,
onSave,
Expand All @@ -1069,11 +1074,11 @@ const ToolbarCreateButton = ({
saving,
submitOnEnter,
...rest
}) => <CreateButton {...rest} />;
}) => <CustomButton {...rest} />;

const PostEditToolbar = props => (
<Toolbar {...props} >
<ToolbarCreateButton />
<ToolbarCustomButton />
</Toolbar>
);
```
Expand Down Expand Up @@ -1486,7 +1491,7 @@ Sometimes, you may want to alter the form values before actually sending them to

* `handleSubmit` which calls the default form save method (provided by react-final-form)
* `handleSubmitWithRedirect` which calls the default form save method and allows to specify a custom redirection

Decorating `handleSubmitWithRedirect` with your own logic allows you to alter the form values before submitting. For instance, to set the `average_note` field value just before submission:

```jsx
Expand All @@ -1499,22 +1504,22 @@ import {
useRedirect,
useNotify,
} from 'react-admin';
const SaveWithNoteButton = ({ handleSubmitWithRedirect, ...props }) => {
const [create] = useCreate('posts');
const redirectTo = useRedirect();
const notify = useNotify();
const { basePath, redirect } = props;
const form = useForm();
const handleClick = useCallback(() => {
// change the average_note field value
form.change('average_note', 10);
handleSubmitWithRedirect('edit');
}, [form]);
// override handleSubmitWithRedirect with custom logic
return <SaveButton {...props} handleSubmitWithRedirect={handleClick} />;
};
Expand Down Expand Up @@ -1545,7 +1550,7 @@ const PostCreateToolbar = props => (
## Using `onSave` To Alter the Form Submission Behavior

The previous technique works well for altering values. But you may want to call a route before submission, or submit the form to different dataProvider methods/resources depending on the form values. And in this case, wrapping `handleSubmitWithRedirect` does not work, because you don't have control on the submission itself.
Instead of *decorating* `handleSubmitWithRedirect`, you can *replace* it, and do the API call manually. You don't have to change anything in the form values in that case. So the previous example can be rewritten as:

```jsx
Expand All @@ -1558,15 +1563,15 @@ import {
useRedirect,
useNotify,
} from 'react-admin';
const SaveWithNoteButton = props => {
const [create] = useCreate('posts');
const redirectTo = useRedirect();
const notify = useNotify();
const { basePath, redirect } = props;
// get values from the form
const formState = useFormState();
const handleClick = useCallback(
() => {
// call dataProvider.create() manually
Expand All @@ -1586,13 +1591,13 @@ const SaveWithNoteButton = props => {
},
[create, notify, redirectTo, basePath, formState, redirect]
);
return <SaveButton {...props} handleSubmitWithRedirect={handleClick} />;
};
```

This technique has a huge drawback, which makes it impractical: by skipping the default `handleSubmitWithRedirect`, this button doesn't trigger form validation. And unfortunately, react-final-form doesn't provide a way to trigger form validation manually.

That's why react-admin provides a way to override just the data provider call and its side effects. It's called `onSave`, and here is how you would use it in the previous use case:

```jsx
Expand All @@ -1604,13 +1609,13 @@ import {
useRedirect,
useNotify,
} from 'react-admin';
const SaveWithNoteButton = props => {
const [create] = useCreate('posts');
const redirectTo = useRedirect();
const notify = useNotify();
const { basePath } = props;
const handleSave = useCallback(
(values, redirect) => {
create(
Expand All @@ -1629,7 +1634,7 @@ const SaveWithNoteButton = props => {
},
[create, notify, redirectTo, basePath]
);
// set onSave props instead of handleSubmitWithRedirect
return <SaveButton {...props} onSave={handleSave} />;
};
Expand Down

0 comments on commit 1dc5ca6

Please sign in to comment.