Skip to content

Commit

Permalink
Merge pull request #5850 from marmelab/fix-array-input-validation
Browse files Browse the repository at this point in the history
Fix Regression on ArrayInput children validation
  • Loading branch information
fzaninotto authored Feb 2, 2021
2 parents 51f7262 + 758b11f commit 84d7ec2
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 15 deletions.
11 changes: 11 additions & 0 deletions cypress/integration/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ describe('Edit Page', () => {
);
});

it('should validate inputs inside ArrayInput', () => {
EditPostPage.gotoTab(3);

cy.get(EditPostPage.elements.addBacklinkButton).click();

EditPostPage.clickInput('backlinks[0].url');
cy.get(EditPostPage.elements.input('backlinks[0].url')).blur();

cy.contains('Required');
});

it('should change reference list correctly when changing filter', () => {
const EditPostTagsPage = editPageFactory('/#/posts/13');
EditPostTagsPage.navigate();
Expand Down
1 change: 1 addition & 0 deletions cypress/support/EditPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export default url => ({
elements: {
body: 'body',
deleteButton: '.ra-delete-button',
addBacklinkButton: '.button-add-backlinks',
input: (name, type = 'input') => {
if (type === 'rich-text-input') {
return `.ra-input-${name} .ql-editor`;
Expand Down
2 changes: 1 addition & 1 deletion examples/simple/src/posts/PostEdit.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ const PostEdit = ({ permissions, ...props }) => (
<ArrayInput source="backlinks">
<SimpleFormIterator>
<DateInput source="date" />
<TextInput source="url" />
<TextInput source="url" validate={required()} />
</SimpleFormIterator>
</ArrayInput>
<DateInput source="published_at" options={{ locale: 'pt' }} />
Expand Down
32 changes: 21 additions & 11 deletions packages/ra-core/src/form/useFormGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import { useFormContext } from './useFormContext';
import { FieldState } from 'final-form';

type FormGroupState = {
dirty: boolean;
errors: object;
valid: boolean;
invalid: boolean;
pristine: boolean;
dirty: boolean;
touched: boolean;
valid: boolean;
};

/**
Expand Down Expand Up @@ -58,18 +59,23 @@ export const useFormGroup = (name: string): FormGroupState => {
const form = useForm();
const formContext = useFormContext();
const [state, setState] = useState<FormGroupState>({
dirty: false,
errors: undefined,
valid: true,
invalid: false,
pristine: true,
dirty: false,
touched: false,
valid: true,
});

useEffect(() => {
const unsubscribe = form.subscribe(
() => {
const fields = formContext.getGroupFields(name);
const fieldStates = fields.map(form.getFieldState);
const fieldStates = fields
.map(field => {
return form.getFieldState(field);
})
.filter(fieldState => fieldState != undefined); // eslint-disable-line
const newState = getFormGroupState(fieldStates);

setState(oldState => {
Expand All @@ -86,6 +92,7 @@ export const useFormGroup = (name: string): FormGroupState => {
dirty: true,
pristine: true,
valid: true,
touched: true,
}
);
return unsubscribe;
Expand All @@ -102,8 +109,8 @@ export const useFormGroup = (name: string): FormGroupState => {
*/
export const getFormGroupState = (
fieldStates: FieldState<any>[]
): FormGroupState =>
fieldStates.reduce(
): FormGroupState => {
return fieldStates.reduce(
(acc, fieldState) => {
let errors = acc.errors || {};

Expand All @@ -112,20 +119,23 @@ export const getFormGroupState = (
}

const newState = {
dirty: acc.dirty || fieldState.dirty,
errors,
valid: acc.valid && fieldState.valid,
invalid: acc.invalid || fieldState.invalid,
pristine: acc.pristine && fieldState.pristine,
dirty: acc.dirty || fieldState.dirty,
touched: acc.touched || fieldState.touched,
valid: acc.valid && fieldState.valid,
};

return newState;
},
{
dirty: false,
errors: undefined,
valid: true,
invalid: false,
pristine: true,
dirty: false,
valid: true,
touched: false,
}
);
};
2 changes: 1 addition & 1 deletion packages/ra-ui-materialui/src/form/FormTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export const FormTabHeader = ({
className={classnames('form-tab', className, {
[classes.errorTabButton]:
formGroup.invalid &&
formGroup.dirty &&
formGroup.touched &&
location.pathname !== value,
})}
component={Link}
Expand Down
5 changes: 3 additions & 2 deletions packages/ra-ui-materialui/src/input/TranslatableInputsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ export const TranslatableInputsTab = (
props: TranslatableInputsTabProps & TabProps
) => {
const { groupKey = '', locale, classes: classesOverride, ...rest } = props;
const { invalid } = useFormGroup(`${groupKey}${locale}`);
const { invalid, touched } = useFormGroup(`${groupKey}${locale}`);

const classes = useStyles(props);
const translate = useTranslate();

Expand All @@ -23,7 +24,7 @@ export const TranslatableInputsTab = (
label={translate(`ra.locales.${locale}`, {
_: capitalize(locale),
})}
className={invalid ? classes.error : undefined}
className={invalid && touched ? classes.error : undefined}
{...rest}
/>
);
Expand Down

0 comments on commit 84d7ec2

Please sign in to comment.