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

[Docs]: Improve buttons sanitation explanation. #4621

Merged
merged 3 commits into from
Apr 7, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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