diff --git a/cypress/integration/edit.js b/cypress/integration/edit.js index c0f76a6b5d..b3006bd630 100644 --- a/cypress/integration/edit.js +++ b/cypress/integration/edit.js @@ -145,4 +145,18 @@ describe('Edit Page', () => { expect(el).to.have.value(date) ); }); + + it('should persit emptied inputs', () => { + EditPostPage.navigate(); + EditPostPage.gotoTab(3); + cy.contains('Tech').click(); + cy.get('li[aria-label="Clear value"]').click(); + EditPostPage.submit(); + + EditPostPage.navigate(); + EditPostPage.gotoTab(3); + cy.get(EditPostPage.elements.input('category')).should(el => + expect(el).to.have.value('') + ); + }); }); diff --git a/examples/simple/src/posts/PostEdit.js b/examples/simple/src/posts/PostEdit.js index d5825bbb0a..13341fabf7 100644 --- a/examples/simple/src/posts/PostEdit.js +++ b/examples/simple/src/posts/PostEdit.js @@ -136,6 +136,7 @@ const PostEdit = ({ permissions, ...props }) => ( { + // For every field initialy provided, we check wether it value has been removed + // and set it explicitly to an empty string + const initialValuesWithEmptyFields = Object.keys(initialValues).reduce( + (acc, key) => { + if (typeof values[key] === 'object' && values[key] !== null) { + acc[key] = sanitizeEmptyValues(initialValues[key], values[key]); + } else { + acc[key] = + typeof values[key] === 'undefined' ? '' : values[key]; + } + return acc; + }, + {} + ); + + // Finaly, we merge back the values to not miss any which wasn't initialy provided + return merge(initialValuesWithEmptyFields, values); +}; + +export default sanitizeEmptyValues; diff --git a/packages/ra-ui-materialui/src/form/SimpleForm.js b/packages/ra-ui-materialui/src/form/SimpleForm.js index f49810ae3b..a1df694665 100644 --- a/packages/ra-ui-materialui/src/form/SimpleForm.js +++ b/packages/ra-ui-materialui/src/form/SimpleForm.js @@ -3,7 +3,11 @@ import PropTypes from 'prop-types'; import { Form } from 'react-final-form'; import arrayMutators from 'final-form-arrays'; import classnames from 'classnames'; -import { useTranslate, useInitializeFormWithRecord } from 'ra-core'; +import { + useTranslate, + useInitializeFormWithRecord, + sanitizeEmptyValues, +} from 'ra-core'; import getFormInitialValues from './getFormInitialValues'; import FormInput from './FormInput'; @@ -20,20 +24,25 @@ const SimpleForm = ({ initialValues, defaultValue, saving, ...props }) => { }; const translate = useTranslate(); + + const finalInitialValues = getFormInitialValues( + initialValues, + defaultValue, + props.record + ); + const submit = values => { const finalRedirect = typeof redirect === undefined ? props.redirect : redirect.current; - props.save(values, finalRedirect); + const finalValues = sanitizeEmptyValues(finalInitialValues, values); + + props.save(finalValues, finalRedirect); }; return (
{ const translate = useTranslate(); const classes = useStyles(); + const finalInitialValues = getFormInitialValues( + initialValues, + defaultValue, + props.record + ); + const submit = values => { const finalRedirect = typeof redirect === undefined ? props.redirect : redirect.current; - props.save(values, finalRedirect); + const finalValues = sanitizeEmptyValues(finalInitialValues, values); + + props.save(finalValues, finalRedirect); }; return ( {allowEmpty ? ( - + {renderEmptyItemOption()} ) : null}