Skip to content

Commit

Permalink
Fix ArrayInput children initialValue override the record value
Browse files Browse the repository at this point in the history
  • Loading branch information
Travis CI committed Dec 3, 2021
1 parent 3324228 commit ab27b0e
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 83 deletions.
10 changes: 10 additions & 0 deletions examples/simple/src/posts/PostEdit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,16 @@ const PostEdit = ({ permissions, ...props }) => {
/>
<BooleanInput source="commentable" defaultValue />
<TextInput disabled source="views" />
<ArrayInput source="pictures">
<SimpleFormIterator>
<TextInput source="url" initialValue="" />
<ArrayInput source="metas.authors">
<SimpleFormIterator>
<TextInput source="name" initialValue="" />
</SimpleFormIterator>
</ArrayInput>
</SimpleFormIterator>
</ArrayInput>
</FormTab>
<FormTab label="post.form.comments">
<ReferenceManyField
Expand Down
4 changes: 2 additions & 2 deletions packages/ra-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@
"@types/react-router-dom": "^5.1.0",
"connected-react-router": "^6.5.2",
"cross-env": "^5.2.0",
"final-form": "^4.20.2",
"final-form": "^4.20.4",
"history": "^4.7.2",
"ignore-styles": "~5.0.1",
"ra-test": "^3.19.2",
"react": "^17.0.0",
"react-dom": "^17.0.0",
"react-final-form": "^6.5.2",
"react-final-form": "^6.5.7",
"react-redux": "^7.1.0",
"react-router": "^5.1.0",
"react-router-dom": "^5.1.0",
Expand Down
73 changes: 38 additions & 35 deletions packages/ra-core/src/form/FormWithRedirect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import {
OnFailure,
} from '../types';
import { RedirectionSideEffect } from '../sideEffect';
import { setAutomaticRefresh } from '../actions/uiActions';
import { setAutomaticRefresh } from '../actions';
import { RecordContextProvider, useRecordContext } from '../controller';
import { FormContextProvider } from './FormContextProvider';
import submitErrorsMutators from './submitErrorsMutators';
import useWarnWhenUnsavedChanges from './useWarnWhenUnsavedChanges';
Expand Down Expand Up @@ -55,7 +56,6 @@ const FormWithRedirect = ({
initialValuesEqual,
keepDirtyOnReinitialize = true,
mutators = defaultMutators,
record,
render,
save,
saving,
Expand All @@ -67,6 +67,7 @@ const FormWithRedirect = ({
sanitizeEmptyValues: shouldSanitizeEmptyValues = true,
...props
}: FormWithRedirectProps) => {
const record = useRecordContext(props);
const redirect = useRef(props.redirect);
const onSave = useRef(save);
const formGroups = useRef<{ [key: string]: string[] }>({});
Expand Down Expand Up @@ -158,38 +159,40 @@ const FormWithRedirect = ({
};

return (
<FormContextProvider value={formContextValue}>
<Form
key={`${version}_${record?.id || ''}`} // support for refresh button
debug={debug}
decorators={decorators}
destroyOnUnregister={destroyOnUnregister}
form={form}
initialValues={finalInitialValues}
initialValuesEqual={initialValuesEqual}
keepDirtyOnReinitialize={keepDirtyOnReinitialize}
mutators={finalMutators} // necessary for ArrayInput
onSubmit={submit}
subscription={subscription} // don't redraw entire form each time one field changes
validate={validate}
validateOnBlur={validateOnBlur}
render={formProps => (
// @ts-ignore Ignored because of a weird error about the active prop
<FormView
{...props}
{...formProps}
key={`${version}_${record?.id || ''}`} // support for refresh button
record={record}
setRedirect={setRedirect}
saving={formProps.submitting || saving}
render={render}
save={save}
warnWhenUnsavedChanges={warnWhenUnsavedChanges}
formRootPathname={formRootPathname}
/>
)}
/>
</FormContextProvider>
<RecordContextProvider value={record}>
<FormContextProvider value={formContextValue}>
<Form
key={`${version}_${record?.id || ''}`} // support for refresh button
debug={debug}
decorators={decorators}
destroyOnUnregister={destroyOnUnregister}
form={form}
initialValues={finalInitialValues}
initialValuesEqual={initialValuesEqual}
keepDirtyOnReinitialize={keepDirtyOnReinitialize}
mutators={finalMutators} // necessary for ArrayInput
onSubmit={submit}
subscription={subscription} // don't redraw entire form each time one field changes
validate={validate}
validateOnBlur={validateOnBlur}
render={formProps => (
// @ts-ignore Ignored because of a weird error about the active prop
<FormView
{...props}
{...formProps}
key={`${version}_${record?.id || ''}`} // support for refresh button
record={record}
setRedirect={setRedirect}
saving={formProps.submitting || saving}
render={render}
save={save}
warnWhenUnsavedChanges={warnWhenUnsavedChanges}
formRootPathname={formRootPathname}
/>
)}
/>
</FormContextProvider>
</RecordContextProvider>
);
};

Expand All @@ -216,7 +219,7 @@ export type FormWithRedirectSave = (
export interface FormWithRedirectOwnProps {
defaultValue?: any;
formRootPathname?: string;
record?: RaRecord;
record?: Partial<RaRecord>;
redirect?: RedirectionSideEffect;
render: FormWithRedirectRender;
save?: FormWithRedirectSave;
Expand Down
56 changes: 29 additions & 27 deletions packages/ra-core/src/form/useInput.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import * as React from 'react';
import { FunctionComponent, ReactElement } from 'react';
import { render, fireEvent } from '@testing-library/react';
import { Form, useFormState } from 'react-final-form';
import { renderWithRedux } from 'ra-test';
import { RecordContextProvider } from '../controller';
import FormWithRedirect from './FormWithRedirect';
import useInput, { InputProps } from './useInput';
import { required } from './validate';
import { renderWithRedux } from 'ra-test';

const Input: FunctionComponent<
{ children: (props: any) => ReactElement } & InputProps
Expand Down Expand Up @@ -208,30 +209,31 @@ describe('useInput', () => {

it('does not apply the initialValue when input has a value of 0', () => {
const { queryByDisplayValue } = renderWithRedux(
<FormWithRedirect
onSubmit={jest.fn()}
record={{ id: 1, views: 0 }}
render={() => {
return (
<Input
source="views"
resource="posts"
initialValue={99}
>
{({ id, input }) => {
return (
<input
type="number"
id={id}
aria-label="Views"
{...input}
/>
);
}}
</Input>
);
}}
/>
<RecordContextProvider value={{ id: 1, views: 0 }}>
<FormWithRedirect
onSubmit={jest.fn()}
render={() => {
return (
<Input
source="views"
resource="posts"
initialValue={99}
>
{({ id, input }) => {
return (
<input
type="number"
id={id}
aria-label="Views"
{...input}
/>
);
}}
</Input>
);
}}
/>
</RecordContextProvider>
);
expect(queryByDisplayValue('99')).toBeNull();
});
Expand Down Expand Up @@ -306,8 +308,8 @@ describe('useInput', () => {
it('does not apply the initialValue true when the field is of type checkbox and has a value', () => {
const { queryByText } = renderWithRedux(
<FormWithRedirect
onSubmit={jest.fn()}
record={{ id: 1, is_published: false }}
onSubmit={jest.fn()}
render={() => (
<BooleanInput source="is_published" initialValue={true} />
)}
Expand All @@ -319,8 +321,8 @@ describe('useInput', () => {
it('does not apply the initialValue false when the field is of type checkbox and has a value', () => {
const { queryByText } = renderWithRedux(
<FormWithRedirect
onSubmit={jest.fn()}
record={{ id: 1, is_published: true }}
onSubmit={jest.fn()}
render={() => (
<BooleanInput source="is_published" initialValue={false} />
)}
Expand Down
9 changes: 8 additions & 1 deletion packages/ra-core/src/form/useInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import {
FieldRenderProps,
FieldInputProps,
} from 'react-final-form';
import get from 'lodash/get';
import { Validator, composeValidators } from './validate';
import isRequired from './isRequired';
import { useFormGroupContext } from './useFormGroupContext';
import { useFormContext } from './useFormContext';
import { useRecordContext } from '../controller';

export interface InputProps<T = any>
extends Omit<
Expand Down Expand Up @@ -51,6 +53,7 @@ const useInput = ({
const finalName = name || source;
const formGroupName = useFormGroupContext();
const formContext = useFormContext();
const record = useRecordContext();

useEffect(() => {
if (!formContext || !formGroupName) {
Expand All @@ -67,8 +70,12 @@ const useInput = ({
? composeValidators(validate)
: validate;

// Fetch the initialValue from the record if available or apply the provided initialValue.
// This ensure dynamically added inputs have their value set correctly (ArrayInput for example).
// We don't do this for the form level initialValues so that it works as it should in final-form
// (ie. field level initialValue override form level initialValues for this field).
const { input, meta } = useFinalFormField(finalName, {
initialValue,
initialValue: get(record, source, initialValue),
defaultValue,
validate: sanitizedValidate,
...options,
Expand Down
2 changes: 1 addition & 1 deletion packages/ra-test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"@types/react-router-dom": "^5.1.0",
"connected-react-router": "^6.5.2",
"cross-env": "^5.2.0",
"final-form": "^4.20.2",
"final-form": "^4.20.4",
"history": "^4.7.2",
"ignore-styles": "~5.0.1",
"ra-core": "^3.19.2",
Expand Down
4 changes: 2 additions & 2 deletions packages/ra-ui-materialui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@
"@types/query-string": "5.1.0",
"cross-env": "^5.2.0",
"file-api": "~0.10.4",
"final-form": "^4.20.2",
"final-form": "^4.20.4",
"final-form-arrays": "^3.0.2",
"ignore-styles": "~5.0.1",
"ra-core": "^3.19.2",
"ra-test": "^3.19.2",
"react": "^17.0.0",
"react-dom": "^17.0.0",
"react-final-form": "^6.5.2",
"react-final-form": "^6.5.7",
"react-final-form-arrays": "^3.1.3",
"react-redux": "^7.1.0",
"react-router": "^5.1.0",
Expand Down
8 changes: 5 additions & 3 deletions packages/ra-ui-materialui/src/input/BooleanInput.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import * as React from 'react';
import { render, fireEvent } from '@testing-library/react';
import { Form } from 'react-final-form';
import { renderWithRedux } from 'ra-test';
import { FormWithRedirect } from 'ra-core';

import BooleanInput from './BooleanInput';

Expand Down Expand Up @@ -90,10 +92,10 @@ describe('<BooleanInput />', () => {
});

it('should be checked if the value is true and initialValue is false', () => {
const { getByLabelText } = render(
<Form
const { getByLabelText } = renderWithRedux(
<FormWithRedirect
onSubmit={jest.fn}
initialValues={{ isPublished: true }}
record={{ isPublished: true }}
render={() => (
<BooleanInput {...defaultProps} initialValue={false} />
)}
Expand Down
4 changes: 2 additions & 2 deletions packages/react-admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@
"@material-ui/icons": "^4.11.2",
"@material-ui/styles": "^4.11.2",
"connected-react-router": "^6.5.2",
"final-form": "^4.20.2",
"final-form": "^4.20.4",
"final-form-arrays": "^3.0.2",
"ra-core": "^3.19.2",
"ra-i18n-polyglot": "^3.19.2",
"ra-language-english": "^3.19.2",
"ra-ui-materialui": "^3.19.2",
"react-final-form": "^6.5.2",
"react-final-form": "^6.5.7",
"react-final-form-arrays": "^3.1.3",
"react-redux": "^7.1.0",
"react-router": "^5.1.0",
Expand Down
20 changes: 10 additions & 10 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1626,7 +1626,7 @@
dependencies:
regenerator-runtime "^0.13.4"

"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
version "7.16.3"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.3.tgz#b86f0db02a04187a3c17caa77de69840165d42d5"
integrity sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==
Expand Down Expand Up @@ -8932,10 +8932,10 @@ final-form-arrays@^3.0.2:
resolved "https://registry.yarnpkg.com/final-form-arrays/-/final-form-arrays-3.0.2.tgz#9f3bef778dec61432357744eb6f3abef7e7f3847"
integrity sha512-TfO8aZNz3RrsZCDx8GHMQcyztDNpGxSSi9w4wpSNKlmv2PfFWVVM8P7Yj5tj4n0OWax+x5YwTLhT5BnqSlCi+w==

final-form@^4.20.2:
version "4.20.2"
resolved "https://registry.yarnpkg.com/final-form/-/final-form-4.20.2.tgz#c820b37d7ebb73d71169480256a36c7e6e6c9155"
integrity sha512-5i0IxqwjjPG1nUNCjWhqPCvQJJ2R+QwTwaAnjPmFnLbyjIHWuBPU8u+Ps4G3TcX2Sjno+O5xCZJzYcMJEzzfCQ==
final-form@^4.20.4:
version "4.20.4"
resolved "https://registry.yarnpkg.com/final-form/-/final-form-4.20.4.tgz#8d59e36d3248a227265cc731d76c0564dd2606f6"
integrity sha512-hyoOVVilPLpkTvgi+FSJkFZrh0Yhy4BhE6lk/NiBwrF4aRV8/ykKEyXYvQH/pfUbRkOosvpESYouFb+FscsLrw==
dependencies:
"@babel/runtime" "^7.10.0"

Expand Down Expand Up @@ -15501,12 +15501,12 @@ react-final-form-arrays@^3.1.3:
dependencies:
"@babel/runtime" "^7.12.1"

react-final-form@^6.5.2:
version "6.5.2"
resolved "https://registry.yarnpkg.com/react-final-form/-/react-final-form-6.5.2.tgz#d04d1eb7d92eabc6f6c35206bb0eebfc4bfd924b"
integrity sha512-c5l45FYOoxtfpvsvMFh3w2WW8KNxbuebBUrM16rUrooQkewTs0Zahmv0TuKFX5jsC9BKn5Fo84j3ZVXQdURS4w==
react-final-form@^6.5.7:
version "6.5.7"
resolved "https://registry.yarnpkg.com/react-final-form/-/react-final-form-6.5.7.tgz#0c1098accf0f0011adee5a46076ed1b99ed1b1ea"
integrity sha512-o7tvJXB+McGiXOILqIC8lnOcX4aLhIBiF/Xi9Qet35b7XOS8R7KL8HLRKTfnZWQJm6MCE15v1U0SFive0NcxyA==
dependencies:
"@babel/runtime" "^7.12.1"
"@babel/runtime" "^7.15.4"

"react-is@^16.12.0 || ^17.0.0", "react-is@^16.8.0 || ^17.0.0", react-is@^17.0.1:
version "17.0.1"
Expand Down

0 comments on commit ab27b0e

Please sign in to comment.