<SaveButton>
The <SaveButton>
component is a button that is used to submit a form.
<SaveButton>
calls the save
function defined by the main page component (<Create>
or <Edit>
), which it grabs from the SaveContext
.
Usage
Create a <SaveButton>
with custom UI options, or custom side effects, then use that button in a custom <Toolbar>
that you can inject to <SimpleForm>
or <TabbedForm>
using the toolbar
prop:
import { SaveButton, Toolbar, Edit, SimpleForm, useNotify, useRedirect } from 'react-admin';
const PostSaveButton = () => {
const notify = useNotify();
const redirect = useRedirect();
const onSuccess = data => {
notify(`Post "${data.title}" saved!`);
redirect('/posts');
};
return (
<SaveButton type="button" mutationOptions= />
);
};
const PostEditToolbar = () => (
<Toolbar>
<PostSaveButton />
<DeleteButton />
</Toolbar>
);
const PostEdit = () => (
<Edit>
<SimpleForm toolbar={<PostEditToolbar />}>
...
</SimpleForm>
</Edit>
);
<SaveButton>
accepts the following props:
Additional props (e.g. color
, variant
) are passed to the underlying Material UI <Button>
component.
icon
By default, <SaveButton>
renders a disk icon. You can can pass another icon element:
import AddBoxIcon from '@mui/icons-material/AddBox';
import { SaveButton } from 'react-admin';
const MySaveButton = () => <SaveButton icon={<AddBoxIcon />} />;
label
By default, <SaveButton>
renders with the “Save” (translated if the user locale isn’t English), whether used on a creation or edition form. You can pass another label:
const PostCreateToolbar = () => (
<Toolbar>
<SaveButton label="Create post" />
</Toolbar>
);
Tip: The label will go through the useTranslate
hook, so you can use translation keys.
mutationOptions
You can override the mutationOptions
of the main mutation query (dataProvider.create()
or dataProvider.update()
) by passing a mutationOptions
prop to <SaveButton>
. This is useful when you have more than one save button.
For instance, to display two save buttons in a creation form, one to save and redirect to the edition page, and the second to save and empty the form:
import { Toolbar, SaveButton, useRedirect, useNotify } from 'react-admin';
import { useFormContext } from 'react-hook-form';
const MyToolbar = () => {
const { reset } = useFormContext();
const notify = useNotify();
return (
<Toolbar>
<SaveButton label="Save" />
<SaveButton
label="Save and add"
mutationOptions={{
onSuccess: () => {
notify('Element created');
reset();
}}
}
type="button"
variant="text"
/>
</Toolbar>
);
};
Tip: When using custom mutationOptions
, you must set the button type
to button
instead of the default submit
, otherwise it’s the main page’s mutationOptions
that is used.
onClick
You can add an event handler to the <SaveButton>
by passing an onClick
callback.
const PostCreateToolbar = () => (
<Toolbar>
<SaveButton label="Save" onClick={() => alert('Saving...')} />
</Toolbar>
);
onClick
doesn’t replace the default submission handler, since a default SaveButton
is a submit button, but is instead called before it. To override the default submission handler, wrap a <SaveButton>
in a custom SaveContext
.
Note that if you call event.preventDefault()
in onClick
, the form will not be submitted.
This is especially useful preventing the <Form>
from being submitted by pressing the ENTER
key.
By default, pressing ENTER
in any of the form inputs submits the form - this is the expected behavior in most cases. To disable the automated form submission on enter, set the type
prop of the SaveButton
component to button
.
const MyToolbar = () => (
<Toolbar>
<SaveButton type="button" />
<DeleteButton />
</Toolbar>
);
export const PostEdit = () => (
<Edit>
<SimpleForm toolbar={<MyToolbar/>}>
...
</SimpleForm>
</Edit>
);
However, some of your custom input components (e.g. Google Maps widget) may have special handlers for the ENTER
key. In that case, you should prevent the default handling of the event on those inputs. This would allow other inputs to still submit the form on Enter:
export const PostEdit = () => (
<Edit>
<SimpleForm>
<TextInput
source="name"
onKeyUp={event => {
if (event.key === 'Enter') {
event.stopPropagation();
}
}}
/>
</SimpleForm>
</Edit>
);
Tip: <SaveButton type="button">
does not take into account a custom onSubmit
prop passed to the enclosing <Form>
. If you need to override the default submit callback for a <SaveButton type="button">
, you should include an onClick
prop in the button.
const MyToolbar = () => {
const [update] = useUpdate();
const { getValues } = useFormContext();
const redirect = useRedirect();
const handleClick = e => {
e.preventDefault(); // necessary to prevent default SaveButton submit logic
const { id, ...data } = getValues();
update(
'posts',
{ id, data },
{ onSuccess: () => { redirect('list'); }}
);
};
return (
<Toolbar>
<SaveButton type="button" onClick={handleClick} />
<DeleteButton />
</Toolbar>
);
};
export const PostEdit = () => (
<Edit>
<SimpleForm toolbar={<MyToolbar/>}>
...
</SimpleForm>
</Edit>
);
alwaysEnable
By default, the <SaveButton>
rendered by <Toolbar>
is disabled until there is something to save, i.e. until the user changes at least one input. Set alwaysEnable
to true
to always enable the button.
import { Toolbar, SaveButton } from 'react-admin';
const MyToolbar = () => (
<Toolbar>
<SaveButton alwaysEnable />
</Toolbar>
);
sx
: CSS API
The <SaveButton>
components accept the usual className
prop, but you can override many class names injected to the inner components by React-admin thanks to the sx
property (see the sx
documentation for syntax and examples).
const PostCreateToolbar = () => (
<Toolbar>
<SaveButton label="Save" sx={{ margin: 2 }} />
</Toolbar>
);
To override the style of all instances of <SaveButton>
components using the application-wide style overrides, use the RaSaveButton
key.
transform
A <SaveButton>
can specify a callback to transform the record before it is saved. This overrides the transform
prop defined in the main page <Edit>
or <Create>
component.
const transformUser = data => ({
...data,
fullName: `${data.firstName} ${data.lastName}`
});
const UserCreateToolbar = () => (
<Toolbar>
<SaveButton transform={transformUser} />
</Toolbar>
);
type
By default, <SaveButton>
renders a submit
button. You can change this by passing type="button"
. It is especially useful when using more than one save button in a form:
import { Toolbar, SaveButton, useRedirect, useNotify } from 'react-admin';
import { useFormContext } from 'react-hook-form';
const MyToolbar = () => {
const { reset } = useFormContext();
const notify = useNotify();
return (
<Toolbar>
<SaveButton label="Save" />
<SaveButton
label="Save and add"
mutationOptions={{
onSuccess: () => {
notify('Element created');
reset();
}}
}
type="button"
variant="text"
/>
</Toolbar>
);
};