Skip to content
Merged
Show file tree
Hide file tree
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
28 changes: 15 additions & 13 deletions packages/ra-ui-materialui/src/button/SaveButton.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ import {
NumberInput,
} from '../input';
import { AdminContext } from '../AdminContext';
import {
AlwaysEnable,
Basic,
EnabledWhenFormIsPrefilled,
} from './SaveButton.stories';

const invalidButtonDomProps = {
disabled: true,
Expand Down Expand Up @@ -64,13 +69,7 @@ describe('<SaveButton />', () => {
});

it('should render as submit type by default', async () => {
render(
<AdminContext dataProvider={testDataProvider()}>
<Form>
<SaveButton />
</Form>
</AdminContext>
);
render(<Basic />);
await waitFor(() =>
expect(
screen.getByLabelText('ra.action.save').getAttribute('type')
Expand Down Expand Up @@ -388,13 +387,16 @@ describe('<SaveButton />', () => {
});

it('should render enabled if alwaysEnable is true', async () => {
render(
<AdminContext dataProvider={testDataProvider()}>
<Form>
<SaveButton alwaysEnable={true} />
</Form>
</AdminContext>
render(<AlwaysEnable />);
await waitFor(() =>
expect(screen.getByLabelText('ra.action.save')['disabled']).toEqual(
false
)
);
});

it('should render enabled if the form is prefilled', async () => {
render(<EnabledWhenFormIsPrefilled />);
await waitFor(() =>
expect(screen.getByLabelText('ra.action.save')['disabled']).toEqual(
false
Expand Down
70 changes: 46 additions & 24 deletions packages/ra-ui-materialui/src/button/SaveButton.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { Form } from 'ra-core';
import { Form, TestMemoryRouter } from 'ra-core';
import { Paper } from '@mui/material';

import { SaveButton } from './SaveButton';
Expand Down Expand Up @@ -29,33 +29,55 @@ const MakeFormChange = () => {
};

export const Dirty = () => (
<AdminContext>
<Paper>
<Form>
<MakeFormChange />
<SaveButton />
</Form>
</Paper>
</AdminContext>
<TestMemoryRouter>
<AdminContext>
<Paper>
<Form>
<MakeFormChange />
<SaveButton />
</Form>
</Paper>
</AdminContext>
</TestMemoryRouter>
);

export const EnabledWhenFormIsPrefilled = () => (
<TestMemoryRouter
initialEntries={[
`/posts/create?source=${JSON.stringify({ title: 'foo' })}`,
]}
>
<AdminContext>
<Paper>
<Form>
<SaveButton />
</Form>
</Paper>
</AdminContext>
</TestMemoryRouter>
);

export const AlwaysEnable = () => (
<AdminContext>
<Paper>
<Form>
<SaveButton alwaysEnable />
</Form>
</Paper>
</AdminContext>
<TestMemoryRouter>
<AdminContext>
<Paper>
<Form>
<SaveButton alwaysEnable />
</Form>
</Paper>
</AdminContext>
</TestMemoryRouter>
);

export const Submitting = () => (
<AdminContext>
<Paper>
<Form onSubmit={() => new Promise(() => {})}>
<MakeFormChange />
<SaveButton />
</Form>
</Paper>
</AdminContext>
<TestMemoryRouter>
<AdminContext>
<Paper>
<Form onSubmit={() => new Promise(() => {})}>
<MakeFormChange />
<SaveButton />
</Form>
</Paper>
</AdminContext>
</TestMemoryRouter>
);
9 changes: 7 additions & 2 deletions packages/ra-ui-materialui/src/button/SaveButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
useTranslate,
warning,
setSubmissionErrors,
useRecordFromLocation,
} from 'ra-core';

/**
Expand Down Expand Up @@ -75,12 +76,16 @@ export const SaveButton = <RecordType extends RaRecord = any>(
// useFormState().isDirty might differ from useFormState().dirtyFields (https://github.com/react-hook-form/react-hook-form/issues/4740)
const isDirty = Object.keys(dirtyFields).length > 0;
// Use form isDirty, isValidating and form context saving to enable or disable the save button
// if alwaysEnable is undefined
// if alwaysEnable is undefined and the form wasn't prefilled
const recordFromLocation = useRecordFromLocation();
const disabled = valueOrDefault(
alwaysEnable === false || alwaysEnable === undefined
? undefined
: !alwaysEnable,
disabledProp || !isDirty || isValidating || isSubmitting
disabledProp ||
(!isDirty && recordFromLocation == null) ||
isValidating ||
isSubmitting
);

warning(
Expand Down
Loading