From 7b71060a9727fcf378f90f2194082678f078b540 Mon Sep 17 00:00:00 2001 From: Gildas Garcia <1122076+djhi@users.noreply.github.com> Date: Fri, 18 Aug 2023 12:49:33 +0200 Subject: [PATCH] Fix ArrayInput Does Not Apply Default Values Set On Inputs --- .../ArrayInput/SimpleFormIterator.spec.tsx | 2 +- .../input/ArrayInput/SimpleFormIterator.tsx | 7 +- .../src/input/SelectArrayInput.spec.tsx | 25 ++++++- .../src/input/SelectArrayInput.stories.tsx | 71 +++++++++++++++++++ 4 files changed, 101 insertions(+), 4 deletions(-) diff --git a/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.spec.tsx b/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.spec.tsx index db17686f39a..e3dac119c2c 100644 --- a/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.spec.tsx +++ b/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.spec.tsx @@ -546,7 +546,7 @@ describe('', () => { screen .queryAllByLabelText('Email') .map(inputElement => (inputElement as HTMLInputElement).value) - ).toEqual(['']); + ).toEqual(['default@marmelab.com']); expect( screen .queryAllByLabelText('Name') diff --git a/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.tsx b/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.tsx index 605d753d99f..e2adf566de3 100644 --- a/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.tsx +++ b/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.tsx @@ -21,7 +21,7 @@ import { useRecordContext, useTranslate, } from 'ra-core'; -import { UseFieldArrayReturn } from 'react-hook-form'; +import { UseFieldArrayReturn, useFormContext } from 'react-hook-form'; import { useArrayInput } from './useArrayInput'; import { @@ -60,6 +60,7 @@ export const SimpleFormIterator = (props: SimpleFormIteratorProps) => { } = props; const [confirmIsOpen, setConfirmIsOpen] = useState(false); const { append, fields, move, remove, replace } = useArrayInput(props); + const { resetField } = useFormContext(); const translate = useTranslate(); const record = useRecordContext(props); const initialDefaultValue = useRef({}); @@ -117,8 +118,10 @@ export const SimpleFormIterator = (props: SimpleFormIteratorProps) => { } } append(defaultValue); + // Make sure the newly added inputs are not considered dirty by react-hook-form + resetField(`${source}.${fields.length}`, { defaultValue }); }, - [append, children] + [append, children, resetField, source, fields.length] ); // add field and call the onClick event of the button passed as addButton prop diff --git a/packages/ra-ui-materialui/src/input/SelectArrayInput.spec.tsx b/packages/ra-ui-materialui/src/input/SelectArrayInput.spec.tsx index 9f8e5180b8a..6b429e7fec5 100644 --- a/packages/ra-ui-materialui/src/input/SelectArrayInput.spec.tsx +++ b/packages/ra-ui-materialui/src/input/SelectArrayInput.spec.tsx @@ -7,7 +7,11 @@ import { AdminContext } from '../AdminContext'; import { SimpleForm } from '../form'; import { SelectArrayInput } from './SelectArrayInput'; import { useCreateSuggestionContext } from './useSupportCreateSuggestion'; -import { DifferentIdTypes, TranslateChoice } from './SelectArrayInput.stories'; +import { + DifferentIdTypes, + TranslateChoice, + InsideArrayInput, +} from './SelectArrayInput.stories'; describe('', () => { const defaultProps = { @@ -636,4 +640,23 @@ describe('', () => { ); expect(screen.queryByTestId('selectArray')).toBeDefined(); }); + + it('should always apply its default value inside an ArrayInput', async () => { + render(); + await screen.findByText('Foo'); + fireEvent.click(screen.getByLabelText('Remove')); + await waitFor(() => { + expect(screen.queryByText('Foo')).toBeNull(); + }); + fireEvent.click(screen.getByLabelText('Add')); + await screen.findByText('Foo'); + fireEvent.click(screen.getByLabelText('Remove')); + await waitFor(() => { + expect(screen.queryByText('Foo')).toBeNull(); + }); + fireEvent.click(screen.getByLabelText('Add')); + await screen.findByText('Foo'); + fireEvent.click(screen.getByLabelText('Add')); + expect(await screen.findAllByText('Foo')).toHaveLength(2); + }); }); diff --git a/packages/ra-ui-materialui/src/input/SelectArrayInput.stories.tsx b/packages/ra-ui-materialui/src/input/SelectArrayInput.stories.tsx index a0bb155293e..6ecd1def302 100644 --- a/packages/ra-ui-materialui/src/input/SelectArrayInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/SelectArrayInput.stories.tsx @@ -17,11 +17,26 @@ import { SelectArrayInput } from './SelectArrayInput'; import { ReferenceArrayInput } from './ReferenceArrayInput'; import { useCreateSuggestionContext } from './useSupportCreateSuggestion'; import { TextInput } from './TextInput'; +import { ArrayInput, SimpleFormIterator } from './ArrayInput'; +import { FormDataConsumer } from 'ra-core'; +import { useWatch } from 'react-hook-form'; export default { title: 'ra-ui-materialui/input/SelectArrayInput' }; const i18nProvider = polyglotI18nProvider(() => englishMessages); +const FormInspector = ({ source }) => { + const value = useWatch({ name: source }); + return ( +
+ {source} value in form:  + + {JSON.stringify(value)} ({typeof value}) + +
+ ); +}; + export const Basic = () => ( ( ); +export const DefaultValue = () => ( + + + + + + + +); + +export const InsideArrayInput = () => ( + + + + + + + {({ getSource }) => { + const source = getSource!('data'); + return ( + <> + + + ); + }} + + + + + + + +); + const choices = [ { id: 'admin', name: 'Admin' }, { id: 'u001', name: 'Editor' },