Skip to content

Commit 7256b5e

Browse files
committed
Fix <SaveButton> is not enabled when the form is prefilled (from <CloneButton> for instance)
1 parent e25da34 commit 7256b5e

File tree

3 files changed

+66
-39
lines changed

3 files changed

+66
-39
lines changed

packages/ra-ui-materialui/src/button/SaveButton.spec.tsx

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ import {
2020
NumberInput,
2121
} from '../input';
2222
import { AdminContext } from '../AdminContext';
23+
import {
24+
AlwaysEnable,
25+
Basic,
26+
EnabledWhenFormIsPrefilled,
27+
} from './SaveButton.stories';
2328

2429
const invalidButtonDomProps = {
2530
disabled: true,
@@ -64,13 +69,7 @@ describe('<SaveButton />', () => {
6469
});
6570

6671
it('should render as submit type by default', async () => {
67-
render(
68-
<AdminContext dataProvider={testDataProvider()}>
69-
<Form>
70-
<SaveButton />
71-
</Form>
72-
</AdminContext>
73-
);
72+
render(<Basic />);
7473
await waitFor(() =>
7574
expect(
7675
screen.getByLabelText('ra.action.save').getAttribute('type')
@@ -388,13 +387,16 @@ describe('<SaveButton />', () => {
388387
});
389388

390389
it('should render enabled if alwaysEnable is true', async () => {
391-
render(
392-
<AdminContext dataProvider={testDataProvider()}>
393-
<Form>
394-
<SaveButton alwaysEnable={true} />
395-
</Form>
396-
</AdminContext>
390+
render(<AlwaysEnable />);
391+
await waitFor(() =>
392+
expect(screen.getByLabelText('ra.action.save')['disabled']).toEqual(
393+
false
394+
)
397395
);
396+
});
397+
398+
it('should render enabled if the form is prefilled', async () => {
399+
render(<EnabledWhenFormIsPrefilled />);
398400
await waitFor(() =>
399401
expect(screen.getByLabelText('ra.action.save')['disabled']).toEqual(
400402
false
Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from 'react';
2-
import { Form } from 'ra-core';
2+
import { Form, TestMemoryRouter } from 'ra-core';
33
import { Paper } from '@mui/material';
44

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

3131
export const Dirty = () => (
32-
<AdminContext>
33-
<Paper>
34-
<Form>
35-
<MakeFormChange />
36-
<SaveButton />
37-
</Form>
38-
</Paper>
39-
</AdminContext>
32+
<TestMemoryRouter>
33+
<AdminContext>
34+
<Paper>
35+
<Form>
36+
<MakeFormChange />
37+
<SaveButton />
38+
</Form>
39+
</Paper>
40+
</AdminContext>
41+
</TestMemoryRouter>
42+
);
43+
44+
export const EnabledWhenFormIsPrefilled = () => (
45+
<TestMemoryRouter
46+
initialEntries={[
47+
`/posts/create?source=${JSON.stringify({ title: 'foo' })}`,
48+
]}
49+
>
50+
<AdminContext>
51+
<Paper>
52+
<Form>
53+
<SaveButton />
54+
</Form>
55+
</Paper>
56+
</AdminContext>
57+
</TestMemoryRouter>
4058
);
4159

4260
export const AlwaysEnable = () => (
43-
<AdminContext>
44-
<Paper>
45-
<Form>
46-
<SaveButton alwaysEnable />
47-
</Form>
48-
</Paper>
49-
</AdminContext>
61+
<TestMemoryRouter>
62+
<AdminContext>
63+
<Paper>
64+
<Form>
65+
<SaveButton alwaysEnable />
66+
</Form>
67+
</Paper>
68+
</AdminContext>
69+
</TestMemoryRouter>
5070
);
5171

5272
export const Submitting = () => (
53-
<AdminContext>
54-
<Paper>
55-
<Form onSubmit={() => new Promise(() => {})}>
56-
<MakeFormChange />
57-
<SaveButton />
58-
</Form>
59-
</Paper>
60-
</AdminContext>
73+
<TestMemoryRouter>
74+
<AdminContext>
75+
<Paper>
76+
<Form onSubmit={() => new Promise(() => {})}>
77+
<MakeFormChange />
78+
<SaveButton />
79+
</Form>
80+
</Paper>
81+
</AdminContext>
82+
</TestMemoryRouter>
6183
);

packages/ra-ui-materialui/src/button/SaveButton.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
useTranslate,
1919
warning,
2020
setSubmissionErrors,
21+
useRecordFromLocation,
2122
} from 'ra-core';
2223

2324
/**
@@ -75,12 +76,14 @@ export const SaveButton = <RecordType extends RaRecord = any>(
7576
// useFormState().isDirty might differ from useFormState().dirtyFields (https://github.com/react-hook-form/react-hook-form/issues/4740)
7677
const isDirty = Object.keys(dirtyFields).length > 0;
7778
// Use form isDirty, isValidating and form context saving to enable or disable the save button
78-
// if alwaysEnable is undefined
79+
// if alwaysEnable is undefined and the form wasn't prefilled
80+
const recordFromLocation = useRecordFromLocation();
7981
const disabled = valueOrDefault(
8082
alwaysEnable === false || alwaysEnable === undefined
8183
? undefined
8284
: !alwaysEnable,
83-
disabledProp || !isDirty || isValidating || isSubmitting
85+
(disabledProp || !isDirty || isValidating || isSubmitting) &&
86+
recordFromLocation == null
8487
);
8588

8689
warning(

0 commit comments

Comments
 (0)