From c4193e2d3fbec600198510148b1a1d3c8bdfb8e2 Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Fri, 29 Nov 2019 08:15:40 +0100 Subject: [PATCH 1/2] Fix Form breaks when setting undefined value to object Closes #4035, #4029 --- .../src/form/sanitizeEmptyValues.spec.ts | 48 +++++++++++++++++++ .../ra-core/src/form/sanitizeEmptyValues.ts | 10 +++- 2 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 packages/ra-core/src/form/sanitizeEmptyValues.spec.ts diff --git a/packages/ra-core/src/form/sanitizeEmptyValues.spec.ts b/packages/ra-core/src/form/sanitizeEmptyValues.spec.ts new file mode 100644 index 00000000000..97f5ec11f12 --- /dev/null +++ b/packages/ra-core/src/form/sanitizeEmptyValues.spec.ts @@ -0,0 +1,48 @@ +import expect from 'expect'; +import sanitizeEmptyValues from './sanitizeEmptyValues'; + +describe('sanitizeEmptyValues', () => { + it('should set null or undefined values to null', () => { + expect(sanitizeEmptyValues({ foo: 23 }, {})).toEqual({ foo: null }); + expect(sanitizeEmptyValues({ foo: 'hello' }, {})).toEqual({ + foo: null, + }); + expect(sanitizeEmptyValues({ foo: new Date() }, {})).toEqual({ + foo: null, + }); + expect(sanitizeEmptyValues({ foo: { bar: 2 } }, {})).toEqual({ + foo: null, + }); + }); + it('should set null or undefined deep values to null', () => { + expect(sanitizeEmptyValues({ foo: { bar: 1 } }, { foo: {} })).toEqual({ + foo: { bar: null }, + }); + }); + it('should accept string values', () => { + const str = 'hello'; + expect(sanitizeEmptyValues({ str: null }, { str })).toEqual({ str }); + expect(sanitizeEmptyValues({}, { str })).toEqual({ str }); + }); + it('should accept date values', () => { + const date = new Date(); + expect(sanitizeEmptyValues({ date: null }, { date })).toEqual({ date }); + expect(sanitizeEmptyValues({}, { date })).toEqual({ date }); + }); + it('should accept array values', () => { + const arr = [1, 2, 3]; + expect(sanitizeEmptyValues({ arr: null }, { arr })).toEqual({ arr }); + expect(sanitizeEmptyValues({}, { arr })).toEqual({ arr }); + }); + it('should accept object values', () => { + const obj = { foo: 1 }; + expect(sanitizeEmptyValues({ obj: null }, { obj })).toEqual({ obj }); + expect(sanitizeEmptyValues({}, { obj })).toEqual({ obj }); + }); + it('should accept deep object values', () => { + const obj = { foo: { bar: 1 } }; + expect( + sanitizeEmptyValues({ obj: { foo: null, foo2: 2 } }, { obj }) + ).toEqual({ obj: { foo: { bar: 1 }, foo2: null } }); + }); +}); diff --git a/packages/ra-core/src/form/sanitizeEmptyValues.ts b/packages/ra-core/src/form/sanitizeEmptyValues.ts index 94154bca368..7018c0b5b74 100644 --- a/packages/ra-core/src/form/sanitizeEmptyValues.ts +++ b/packages/ra-core/src/form/sanitizeEmptyValues.ts @@ -13,13 +13,19 @@ import merge from 'lodash/merge'; const sanitizeEmptyValues = (initialValues: object, values: object) => { // For every field initialy provided, we check wether it value has been removed // and set it explicitly to an empty string + if (!initialValues) return values; const initialValuesWithEmptyFields = Object.keys(initialValues).reduce( (acc, key) => { - if (typeof values[key] === 'object' && values[key] !== null) { + if (values[key] instanceof Date || Array.isArray(values[key])) { + acc[key] = values[key]; + } else if ( + typeof values[key] === 'object' && + values[key] !== null + ) { acc[key] = sanitizeEmptyValues(initialValues[key], values[key]); } else { acc[key] = - typeof values[key] === 'undefined' ? '' : values[key]; + typeof values[key] === 'undefined' ? null : values[key]; } return acc; }, From e1a2f9eec75443ca7e187eedaa5b540363646d9e Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Fri, 29 Nov 2019 08:24:10 +0100 Subject: [PATCH 2/2] Fix typos --- packages/ra-core/src/form/sanitizeEmptyValues.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/ra-core/src/form/sanitizeEmptyValues.ts b/packages/ra-core/src/form/sanitizeEmptyValues.ts index 7018c0b5b74..8fd1871b8e5 100644 --- a/packages/ra-core/src/form/sanitizeEmptyValues.ts +++ b/packages/ra-core/src/form/sanitizeEmptyValues.ts @@ -3,15 +3,15 @@ import merge from 'lodash/merge'; /** * Because final-form removes undefined and empty string values completely * (the key for the empty field is removed from the values), we have to check - * wether this value was initially provided so that it is correctly sent to + * whether this value was initially provided so that it is correctly sent to * the backend. - * See https://github.com/final-form/react-final-form/issues/130#issuecomment-493447888 + * @see https://github.com/final-form/react-final-form/issues/130#issuecomment-493447888 * * @param initialValues The initial values provided to the form * @param values The current form values */ const sanitizeEmptyValues = (initialValues: object, values: object) => { - // For every field initialy provided, we check wether it value has been removed + // For every field initially provided, we check whether it value has been removed // and set it explicitly to an empty string if (!initialValues) return values; const initialValuesWithEmptyFields = Object.keys(initialValues).reduce( @@ -32,7 +32,7 @@ const sanitizeEmptyValues = (initialValues: object, values: object) => { {} ); - // Finaly, we merge back the values to not miss any which wasn't initialy provided + // Finally, we merge back the values to not miss any which wasn't initially provided return merge(initialValuesWithEmptyFields, values); };