From 1915ed0adb3bdb1214482c4e5dd4b3e10c452661 Mon Sep 17 00:00:00 2001 From: Heath Chiavettone Date: Fri, 4 Oct 2024 17:40:33 -0700 Subject: [PATCH 1/8] Fix: made small changes to utility functions to fix #3997 and #4322 Fixes #3997 and #4322 - In `@rjsf/utils`, made the following changes: - Updated `mergeDefaultsWithFormData()` to not overwrite a default when the formData has an undefined value - Updated `getClosestMatchingOption()` to improve the scoring function so that an object container that matches a key gets an extra point - In `@rjsf/core`, updated `MultiSchemaField` to call `onChange` after setting the new option in state rather than before - Updated the `CHANGELOG.md` accordingly --- CHANGELOG.md | 6 ++++++ packages/core/src/components/fields/MultiSchemaField.tsx | 5 +++-- packages/utils/src/mergeDefaultsWithFormData.ts | 2 +- packages/utils/src/schema/getClosestMatchingOption.ts | 8 ++++++-- packages/utils/test/mergeDefaultsWithFormData.test.ts | 8 ++++++++ .../utils/test/schema/getClosestMatchingOptionTest.ts | 2 +- 6 files changed, 25 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c23540c7d7..133d2db250 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,10 +18,16 @@ should change the heading of the (upcoming) version to include a major version b # 5.22.0 +## @rjsf/core + +- Updated `MultiSchemaField` to call the `onChange` handler after setting the new option, fixing [#3997](https://github.com/rjsf-team/react-jsonschema-form/issues/3977) + ## @rjsf/utils - Made fields with const property pre-filled and readonly, fixing [#2600](https://github.com/rjsf-team/react-jsonschema-form/issues/2600) - Added `experimental_customMergeAllOf` option to `retrieveSchema` to allow custom merging of `allOf` schemas +- Updated `mergeDefaultsWithFormData()` to not merge `undefined` when there is a proper default for it, fixing [#4322](https://github.com/rjsf-team/react-jsonschema-form/issues/4322) +- Updated `getClosestMatchingOption()` to improve the scoring of sub-property objects that are provided over ones that aren't, fixing [#3997](https://github.com/rjsf-team/react-jsonschema-form/issues/3977) # 5.21.2 diff --git a/packages/core/src/components/fields/MultiSchemaField.tsx b/packages/core/src/components/fields/MultiSchemaField.tsx index c58b080424..7808f3289c 100644 --- a/packages/core/src/components/fields/MultiSchemaField.tsx +++ b/packages/core/src/components/fields/MultiSchemaField.tsx @@ -128,9 +128,10 @@ class AnyOfField { + onChange(newFormData, undefined, this.getFieldId()); + }); }; getFieldId() { diff --git a/packages/utils/src/mergeDefaultsWithFormData.ts b/packages/utils/src/mergeDefaultsWithFormData.ts index e4ace80eff..f6a4f47814 100644 --- a/packages/utils/src/mergeDefaultsWithFormData.ts +++ b/packages/utils/src/mergeDefaultsWithFormData.ts @@ -49,5 +49,5 @@ export default function mergeDefaultsWithFormData( return acc; }, acc); } - return formData; + return formData === undefined ? defaults : formData; } diff --git a/packages/utils/src/schema/getClosestMatchingOption.ts b/packages/utils/src/schema/getClosestMatchingOption.ts index c81ce42c70..400ebab75e 100644 --- a/packages/utils/src/schema/getClosestMatchingOption.ts +++ b/packages/utils/src/schema/getClosestMatchingOption.ts @@ -51,7 +51,7 @@ export function calculateIndexScore, rootSchema: S, schema?: S, - formData: any = {} + formData?: any ): number { let totalScore = 0; if (schema) { @@ -83,7 +83,11 @@ export function calculateIndexScore(validator, rootSchema, value as S, formValue || {}); + if (isObject(formValue)) { + // If the structure is matching then give it a little boost in score + score += 1; + } + return score + calculateIndexScore(validator, rootSchema, value as S, formValue); } if (value.type === guessType(formValue)) { // If the types match, then we bump the score by one diff --git a/packages/utils/test/mergeDefaultsWithFormData.test.ts b/packages/utils/test/mergeDefaultsWithFormData.test.ts index 919b94ef83..3410b0de78 100644 --- a/packages/utils/test/mergeDefaultsWithFormData.test.ts +++ b/packages/utils/test/mergeDefaultsWithFormData.test.ts @@ -17,6 +17,14 @@ describe('mergeDefaultsWithFormData()', () => { expect(mergeDefaultsWithFormData(undefined, [2])).toEqual([2]); }); + it('should return default when formData is undefined', () => { + expect(mergeDefaultsWithFormData({}, undefined)).toEqual({}); + }); + + it('should return undefined when formData is undefined', () => { + expect(mergeDefaultsWithFormData(undefined, undefined)).toBeUndefined(); + }); + it('should merge two one-level deep objects', () => { expect(mergeDefaultsWithFormData({ a: 1 }, { b: 2 })).toEqual({ a: 1, diff --git a/packages/utils/test/schema/getClosestMatchingOptionTest.ts b/packages/utils/test/schema/getClosestMatchingOptionTest.ts index 5809ea0875..da16f32573 100644 --- a/packages/utils/test/schema/getClosestMatchingOptionTest.ts +++ b/packages/utils/test/schema/getClosestMatchingOptionTest.ts @@ -49,7 +49,7 @@ export default function getClosestMatchingOptionTest(testValidator: TestValidato expect(calculateIndexScore(testValidator, oneOfSchema, firstOption, ONE_OF_SCHEMA_DATA)).toEqual(1); }); it('returns 8 for second option in oneOf schema', () => { - expect(calculateIndexScore(testValidator, oneOfSchema, secondOption, ONE_OF_SCHEMA_DATA)).toEqual(8); + expect(calculateIndexScore(testValidator, oneOfSchema, secondOption, ONE_OF_SCHEMA_DATA)).toEqual(9); }); it('returns 1 for a schema that has a type matching the formData type', () => { expect(calculateIndexScore(testValidator, oneOfSchema, { type: 'boolean' }, true)).toEqual(1); From ea3ef9587ebe921ecb8d4809d6fe3bc399e5d452 Mon Sep 17 00:00:00 2001 From: Heath Chiavettone Date: Fri, 18 Oct 2024 15:32:28 -0700 Subject: [PATCH 2/8] - In order to avoid regressions, added a new `mergeDefaultsWithFormData` prop to the `Experimental_DefaultFormStateBehavior` - Updated `mergeDefaultsWithFormData()` to add new optional `defaultSupercedesUndefined` that when true uses the defaults rather than `undefined` formData - Updated `getDefaultFormState()` to pass true to `mergeDefaultsWithFormData` for `defaultSupercedesUndefined` when `mergeDefaultsIntoFormData` has the value `useDefaultIfFormDataUndefined` - Updated the documentation for the new capabilities - Updated the playground to add controls for the new `mergeDefaultsIntoFormData` option - moved the `Show Error List` component over one column, making it inline radio buttons rather than a select --- CHANGELOG.md | 17 ++++++-- packages/core/package.json | 2 +- .../docs/docs/api-reference/form-props.md | 11 ++++++ .../docs/api-reference/utility-functions.md | 3 ++ packages/playground/src/components/Header.tsx | 39 ++++++++++++++++--- .../utils/src/mergeDefaultsWithFormData.ts | 22 ++++++++--- .../utils/src/schema/getDefaultFormState.ts | 8 ++-- packages/utils/src/types.ts | 12 +++++- .../test/mergeDefaultsWithFormData.test.ts | 8 +++- .../test/schema/getDefaultFormStateTest.ts | 33 ++++++++++++++++ 10 files changed, 133 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 133d2db250..0a06c0f81e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,14 +20,23 @@ should change the heading of the (upcoming) version to include a major version b ## @rjsf/core -- Updated `MultiSchemaField` to call the `onChange` handler after setting the new option, fixing [#3997](https://github.com/rjsf-team/react-jsonschema-form/issues/3977) +- Updated `MultiSchemaField` to call the `onChange` handler after setting the new option, fixing [#3997](https://github.com/rjsf-team/react-jsonschema-form/issues/3977) and [#4314](https://github.com/rjsf-team/react-jsonschema-form/issues/4314) ## @rjsf/utils +- Added `experimental_customMergeAllOf` option to `retrieveSchema()` and `getDefaultFormState()` to allow custom merging of `allOf` schemas - Made fields with const property pre-filled and readonly, fixing [#2600](https://github.com/rjsf-team/react-jsonschema-form/issues/2600) -- Added `experimental_customMergeAllOf` option to `retrieveSchema` to allow custom merging of `allOf` schemas -- Updated `mergeDefaultsWithFormData()` to not merge `undefined` when there is a proper default for it, fixing [#4322](https://github.com/rjsf-team/react-jsonschema-form/issues/4322) -- Updated `getClosestMatchingOption()` to improve the scoring of sub-property objects that are provided over ones that aren't, fixing [#3997](https://github.com/rjsf-team/react-jsonschema-form/issues/3977) +- Added `mergeDefaultsIntoFormData` option to `Experimental_DefaultFormStateBehavior` type to control how to handle merging of defaults +- Updated `mergeDefaultsWithFormData()` to add new optional `defaultSupercedesUndefined` that when true uses the defaults rather than `undefined` formData, fixing [#4322](https://github.com/rjsf-team/react-jsonschema-form/issues/4322) +- Updated `getDefaultFormState()` to pass true to `mergeDefaultsWithFormData` for `defaultSupercedesUndefined` when `mergeDefaultsIntoFormData` has the value `useDefaultIfFormDataUndefined`, fixing [#4322](https://github.com/rjsf-team/react-jsonschema-form/issues/4322) +- Updated `getClosestMatchingOption()` to improve the scoring of sub-property objects that are provided over ones that aren't, fixing [#3997](https://github.com/rjsf-team/react-jsonschema-form/issues/3977) and [#4314](https://github.com/rjsf-team/react-jsonschema-form/issues/4314) + +## Dev / docs / playground + +- Updated the `form-props.md` to add documentation for the new `experimental_customMergeAllOf` props and the `experimental_defaultFormStateBehavior.mergeDefaultsIntoFormData` option +- Updated the `utility-functions.md` to add documentation for the new optional `defaultSupercedesUndefined` parameter and the two missing optional fields on `getDefaultFormState()` +- Updated the playground to add controls for the new `mergeDefaultsIntoFormData` option + - In the process, moved the `Show Error List` component over one column, making it inline radio buttons rather than a select # 5.21.2 diff --git a/packages/core/package.json b/packages/core/package.json index 3044356faf..7ce88986e2 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -14,7 +14,7 @@ "precommit": "lint-staged", "publish-to-npm": "npm run build && npm publish", "test": "jest", - "test:debug": "node --inspect-brk node_modules/.bin/jest", + "test:debug": "node --inspect-brk ../../node_modules/.bin/jest", "test:update": "jest --u", "test:watch": "jest --watch", "test-coverage": "jest --coverage" diff --git a/packages/docs/docs/api-reference/form-props.md b/packages/docs/docs/api-reference/form-props.md index a94910d78e..7cda5b464b 100644 --- a/packages/docs/docs/api-reference/form-props.md +++ b/packages/docs/docs/api-reference/form-props.md @@ -251,6 +251,17 @@ render( ); ``` +### mergeDefaultsIntoFormData + +Optional enumerated flag controlling how the defaults are merged into the form data when dealing with undefined values, defaulting to `useFormDataIfPresent`. + +NOTE: If there is a default for a field and the `formData` is unspecified, the default ALWAYS merges. + +| Flag Value | Description | +| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| `useFormDataIfPresent` | Legacy behavior - Do not merge defaults if there is a value for a field in `formData` even if that value is explicitly set to `undefined` | +| `useDefaultIfFormDataUndefined` | If the value of a field within the `formData` is `undefined`, then use the default value instead | + ## experimental_customMergeAllOf The `experimental_customMergeAllOf` function allows you to provide a custom implementation for merging `allOf` schemas. This can be particularly useful in scenarios where the default [json-schema-merge-allof](https://github.com/mokkabonna/json-schema-merge-allof) library becomes a performance bottleneck, especially with large and complex schemas or doesn't satisfy your needs. diff --git a/packages/docs/docs/api-reference/utility-functions.md b/packages/docs/docs/api-reference/utility-functions.md index 79935921bb..772fb4e0f1 100644 --- a/packages/docs/docs/api-reference/utility-functions.md +++ b/packages/docs/docs/api-reference/utility-functions.md @@ -575,6 +575,7 @@ When merging defaults and form data, we want to merge in this specific way: - [defaults]: T | undefined - The defaults to merge - [formData]: T | undefined - The form data into which the defaults will be merged - [mergeExtraArrayDefaults=false]: boolean - If true, any additional default array entries are appended onto the formData +- [defaultSupercedesUndefined=false]: boolean - If true, an explicit undefined value will be overwritten by the default value #### Returns @@ -897,6 +898,8 @@ Returns the superset of `formData` that includes the given set updated to includ - [formData]: T | undefined - The current formData, if any, onto which to provide any missing defaults - [rootSchema]: S | undefined - The root schema, used to primarily to look up `$ref`s - [includeUndefinedValues=false]: boolean | "excludeObjectChildren" - Optional flag, if true, cause undefined values to be added as defaults. If "excludeObjectChildren", cause undefined values for this object and pass `includeUndefinedValues` as false when computing defaults for any nested object properties. +- [experimental_defaultFormStateBehavior]: Experimental_DefaultFormStateBehavior - See Form props [experimental_defaultFormStateBehavior documentation](./api-reference/form-props.md#experimental_defaultFormStateBehavior) +- [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See Form props [experimental_customMergeAllOf documentation](./api-reference/form-props.md#experimental_customMergeAllOf) #### Returns diff --git a/packages/playground/src/components/Header.tsx b/packages/playground/src/components/Header.tsx index 75979dfde7..a2c77deac3 100644 --- a/packages/playground/src/components/Header.tsx +++ b/packages/playground/src/components/Header.tsx @@ -63,18 +63,18 @@ const liveSettingsBooleanSchema: RJSFSchema = { noValidate: { type: 'boolean', title: 'Disable validation' }, noHtml5Validate: { type: 'boolean', title: 'Disable HTML 5 validation' }, focusOnFirstError: { type: 'boolean', title: 'Focus on 1st Error' }, - }, -}; - -const liveSettingsSelectSchema: RJSFSchema = { - type: 'object', - properties: { showErrorList: { type: 'string', default: 'top', title: 'Show Error List', enum: [false, 'top', 'bottom'], }, + }, +}; + +const liveSettingsSelectSchema: RJSFSchema = { + type: 'object', + properties: { experimental_defaultFormStateBehavior: { title: 'Default Form State Behavior (Experimental)', type: 'object', @@ -157,11 +157,37 @@ const liveSettingsSelectSchema: RJSFSchema = { }, ], }, + mergeDefaultsIntoFormData: { + type: 'string', + title: 'Merge defaults into formData', + default: 'useFormDataIfPresent', + oneOf: [ + { + type: 'string', + title: 'Use undefined field value if present', + enum: ['useFormDataIfPresent'], + }, + { + type: 'string', + title: 'Use default for undefined field value', + enum: ['useDefaultIfFormDataUndefined'], + }, + ], + }, }, }, }, }; +const liveSettingsBooleanUiSchema: UiSchema = { + showErrorList: { + 'ui:widget': 'radio', + 'ui:options': { + inline: true, + }, + }, +}; + const liveSettingsSelectUiSchema: UiSchema = { experimental_defaultFormStateBehavior: { 'ui:options': { @@ -282,6 +308,7 @@ export default function Header({ formData={liveSettings} validator={localValidator} onChange={handleSetLiveSettings} + uiSchema={liveSettingsBooleanUiSchema} >
diff --git a/packages/utils/src/mergeDefaultsWithFormData.ts b/packages/utils/src/mergeDefaultsWithFormData.ts index f6a4f47814..5ffe657725 100644 --- a/packages/utils/src/mergeDefaultsWithFormData.ts +++ b/packages/utils/src/mergeDefaultsWithFormData.ts @@ -12,23 +12,31 @@ import { GenericObjectType } from '../src'; * are deeply merged; additional entries from the defaults are ignored unless `mergeExtraArrayDefaults` is true, in * which case the extras are appended onto the end of the form data * - when the array is not set in form data, the default is copied over - * - scalars are overwritten/set by form data + * - scalars are overwritten/set by form data unless undefined and there is a default AND `defaultSupercedesUndefined` + * is true * * @param [defaults] - The defaults to merge * @param [formData] - The form data into which the defaults will be merged * @param [mergeExtraArrayDefaults=false] - If true, any additional default array entries are appended onto the formData + * @param [defaultSupercedesUndefined=false] - If true, an explicit undefined value will be overwritten by the default value * @returns - The resulting merged form data with defaults */ export default function mergeDefaultsWithFormData( defaults?: T, formData?: T, - mergeExtraArrayDefaults = false + mergeExtraArrayDefaults = false, + defaultSupercedesUndefined = false ): T | undefined { if (Array.isArray(formData)) { const defaultsArray = Array.isArray(defaults) ? defaults : []; const mapped = formData.map((value, idx) => { if (defaultsArray[idx]) { - return mergeDefaultsWithFormData(defaultsArray[idx], value, mergeExtraArrayDefaults); + return mergeDefaultsWithFormData( + defaultsArray[idx], + value, + mergeExtraArrayDefaults, + defaultSupercedesUndefined + ); } return value; }); @@ -44,10 +52,14 @@ export default function mergeDefaultsWithFormData( acc[key as keyof T] = mergeDefaultsWithFormData( defaults ? get(defaults, key) : {}, get(formData, key), - mergeExtraArrayDefaults + mergeExtraArrayDefaults, + defaultSupercedesUndefined ); return acc; }, acc); } - return formData === undefined ? defaults : formData; + if (defaultSupercedesUndefined && formData === undefined) { + return defaults; + } + return formData; } diff --git a/packages/utils/src/schema/getDefaultFormState.ts b/packages/utils/src/schema/getDefaultFormState.ts index f51d41d04a..5217664b8f 100644 --- a/packages/utils/src/schema/getDefaultFormState.ts +++ b/packages/utils/src/schema/getDefaultFormState.ts @@ -586,12 +586,14 @@ export default function getDefaultFormState< // No form data? Use schema defaults. return defaults; } - const { mergeExtraDefaults } = experimental_defaultFormStateBehavior?.arrayMinItems || {}; + const { mergeDefaultsIntoFormData, arrayMinItems = {} } = experimental_defaultFormStateBehavior || {}; + const { mergeExtraDefaults } = arrayMinItems; + const defaultSupercedesUndefined = mergeDefaultsIntoFormData === 'useDefaultIfFormDataUndefined'; if (isObject(formData)) { - return mergeDefaultsWithFormData(defaults as T, formData, mergeExtraDefaults); + return mergeDefaultsWithFormData(defaults as T, formData, mergeExtraDefaults, defaultSupercedesUndefined); } if (Array.isArray(formData)) { - return mergeDefaultsWithFormData(defaults as T[], formData, mergeExtraDefaults); + return mergeDefaultsWithFormData(defaults as T[], formData, mergeExtraDefaults, defaultSupercedesUndefined); } return formData; } diff --git a/packages/utils/src/types.ts b/packages/utils/src/types.ts index ed1ca7aa69..0b6c400504 100644 --- a/packages/utils/src/types.ts +++ b/packages/utils/src/types.ts @@ -66,7 +66,8 @@ export type Experimental_ArrayMinItems = { /** Experimental features to specify different default form state behaviors. Currently, this affects the * handling of optional array fields where `minItems` is set and handling of setting defaults based on the - * value of `emptyObjectFields`. + * value of `emptyObjectFields`. It also affects how `allOf` fields are handled and how to handle merging defaults into + * the formData in relation to explicit `undefined` values via `mergeDefaultsIntoFormData`. */ export type Experimental_DefaultFormStateBehavior = { /** Optional object, that controls how the default form state for arrays with `minItems` is handled. When not provided @@ -86,6 +87,15 @@ export type Experimental_DefaultFormStateBehavior = { * Optional flag to compute the default form state using allOf and if/then/else schemas. Defaults to `skipDefaults'. */ allOf?: 'populateDefaults' | 'skipDefaults'; + /** Optional enumerated flag controlling how the defaults are merged into the form data when dealing with undefined + * values, defaulting to `useFormDataIfPresent`. + * NOTE: If there is a default for a field and the `formData` is unspecified, the default ALWAYS merges. + * - `useFormDataIfPresent`: Legacy behavior - Do not merge defaults if there is a value for a field in `formData`, + * even if that value is explicitly set to `undefined` + * - `useDefaultIfFormDataUndefined`: - If the value of a field within the `formData` is `undefined`, then use the + * default value instead + */ + mergeDefaultsIntoFormData?: 'useFormDataIfPresent' | 'useDefaultIfFormDataUndefined'; }; /** Optional function that allows for custom merging of `allOf` schemas diff --git a/packages/utils/test/mergeDefaultsWithFormData.test.ts b/packages/utils/test/mergeDefaultsWithFormData.test.ts index 3410b0de78..a63f93c686 100644 --- a/packages/utils/test/mergeDefaultsWithFormData.test.ts +++ b/packages/utils/test/mergeDefaultsWithFormData.test.ts @@ -17,8 +17,12 @@ describe('mergeDefaultsWithFormData()', () => { expect(mergeDefaultsWithFormData(undefined, [2])).toEqual([2]); }); - it('should return default when formData is undefined', () => { - expect(mergeDefaultsWithFormData({}, undefined)).toEqual({}); + it('should return formData when formData is undefined', () => { + expect(mergeDefaultsWithFormData({}, undefined)).toEqual(undefined); + }); + + it('should return default when formData is undefined and defaultSupercedesUndefined true', () => { + expect(mergeDefaultsWithFormData({}, undefined, undefined, true)).toEqual({}); }); it('should return undefined when formData is undefined', () => { diff --git a/packages/utils/test/schema/getDefaultFormStateTest.ts b/packages/utils/test/schema/getDefaultFormStateTest.ts index f5cd467e5a..ebbdffb7ec 100644 --- a/packages/utils/test/schema/getDefaultFormStateTest.ts +++ b/packages/utils/test/schema/getDefaultFormStateTest.ts @@ -3743,6 +3743,39 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType expect(getDefaultFormState(testValidator, schema, formData)).toEqual(result); }); }); + describe('object with defaults and undefined in formData, testing mergeDefaultsIntoFormData', () => { + let schema: RJSFSchema; + let defaultedFormData: any; + beforeAll(() => { + schema = { + type: 'object', + properties: { + field: { + type: 'string', + default: 'foo', + }, + }, + required: ['field'], + }; + defaultedFormData = { field: 'foo' }; + }); + it('returns field value of default when formData is empty', () => { + const formData = {}; + expect(getDefaultFormState(testValidator, schema, formData)).toEqual(defaultedFormData); + }); + it('returns field value of undefined when formData has undefined for field', () => { + const formData = { field: undefined }; + expect(getDefaultFormState(testValidator, schema, formData)).toEqual(formData); + }); + it('returns field value of default when formData has undefined for field and `useDefaultIfFormDataUndefined`', () => { + const formData = { field: undefined }; + expect( + getDefaultFormState(testValidator, schema, formData, undefined, undefined, { + mergeDefaultsIntoFormData: 'useDefaultIfFormDataUndefined', + }) + ).toEqual(defaultedFormData); + }); + }); it('should return undefined defaults for a required array property with minItems', () => { const schema: RJSFSchema = { type: 'object', From 6dbde80ca0310dfa0ccc80f9c791c9d5c16e39fe Mon Sep 17 00:00:00 2001 From: Heath Chiavettone Date: Fri, 18 Oct 2024 15:47:07 -0700 Subject: [PATCH 3/8] - Improved documentation a teeny bit --- packages/docs/docs/api-reference/utility-functions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docs/docs/api-reference/utility-functions.md b/packages/docs/docs/api-reference/utility-functions.md index 772fb4e0f1..8dfbfc258b 100644 --- a/packages/docs/docs/api-reference/utility-functions.md +++ b/packages/docs/docs/api-reference/utility-functions.md @@ -898,8 +898,8 @@ Returns the superset of `formData` that includes the given set updated to includ - [formData]: T | undefined - The current formData, if any, onto which to provide any missing defaults - [rootSchema]: S | undefined - The root schema, used to primarily to look up `$ref`s - [includeUndefinedValues=false]: boolean | "excludeObjectChildren" - Optional flag, if true, cause undefined values to be added as defaults. If "excludeObjectChildren", cause undefined values for this object and pass `includeUndefinedValues` as false when computing defaults for any nested object properties. -- [experimental_defaultFormStateBehavior]: Experimental_DefaultFormStateBehavior - See Form props [experimental_defaultFormStateBehavior documentation](./api-reference/form-props.md#experimental_defaultFormStateBehavior) -- [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See Form props [experimental_customMergeAllOf documentation](./api-reference/form-props.md#experimental_customMergeAllOf) +- [experimental_defaultFormStateBehavior]: Experimental_DefaultFormStateBehavior - See Form documentation for the [experimental_defaultFormStateBehavior](./api-reference/form-props.md#experimental_defaultFormStateBehavior) prop +- [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See Form documentation for the [experimental_customMergeAllOf](./api-reference/form-props.md#experimental_customMergeAllOf) prop #### Returns From a349562b13d4ba5274d3144f2ef9d68492bfb47b Mon Sep 17 00:00:00 2001 From: Heath Chiavettone Date: Fri, 18 Oct 2024 15:48:32 -0700 Subject: [PATCH 4/8] - More doc improvements --- packages/docs/docs/api-reference/utility-functions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docs/docs/api-reference/utility-functions.md b/packages/docs/docs/api-reference/utility-functions.md index 8dfbfc258b..41ef4d6760 100644 --- a/packages/docs/docs/api-reference/utility-functions.md +++ b/packages/docs/docs/api-reference/utility-functions.md @@ -898,8 +898,8 @@ Returns the superset of `formData` that includes the given set updated to includ - [formData]: T | undefined - The current formData, if any, onto which to provide any missing defaults - [rootSchema]: S | undefined - The root schema, used to primarily to look up `$ref`s - [includeUndefinedValues=false]: boolean | "excludeObjectChildren" - Optional flag, if true, cause undefined values to be added as defaults. If "excludeObjectChildren", cause undefined values for this object and pass `includeUndefinedValues` as false when computing defaults for any nested object properties. -- [experimental_defaultFormStateBehavior]: Experimental_DefaultFormStateBehavior - See Form documentation for the [experimental_defaultFormStateBehavior](./api-reference/form-props.md#experimental_defaultFormStateBehavior) prop -- [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See Form documentation for the [experimental_customMergeAllOf](./api-reference/form-props.md#experimental_customMergeAllOf) prop +- [experimental_defaultFormStateBehavior]: Experimental_DefaultFormStateBehavior - See `Form` documentation for the [experimental_defaultFormStateBehavior](./api-reference/form-props.md#experimental_defaultFormStateBehavior) prop +- [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See `Form` documentation for the [experimental_customMergeAllOf](./api-reference/form-props.md#experimental_customMergeAllOf) prop #### Returns From 2c9d41816a12cc505f93c5cab305c48792ea5bf0 Mon Sep 17 00:00:00 2001 From: Heath Chiavettone Date: Sun, 20 Oct 2024 16:43:34 -0700 Subject: [PATCH 5/8] - Responded to reviewer feedback --- packages/docs/docs/api-reference/utility-functions.md | 2 +- packages/utils/test/mergeDefaultsWithFormData.test.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/docs/docs/api-reference/utility-functions.md b/packages/docs/docs/api-reference/utility-functions.md index 41ef4d6760..ae839549aa 100644 --- a/packages/docs/docs/api-reference/utility-functions.md +++ b/packages/docs/docs/api-reference/utility-functions.md @@ -899,7 +899,7 @@ Returns the superset of `formData` that includes the given set updated to includ - [rootSchema]: S | undefined - The root schema, used to primarily to look up `$ref`s - [includeUndefinedValues=false]: boolean | "excludeObjectChildren" - Optional flag, if true, cause undefined values to be added as defaults. If "excludeObjectChildren", cause undefined values for this object and pass `includeUndefinedValues` as false when computing defaults for any nested object properties. - [experimental_defaultFormStateBehavior]: Experimental_DefaultFormStateBehavior - See `Form` documentation for the [experimental_defaultFormStateBehavior](./api-reference/form-props.md#experimental_defaultFormStateBehavior) prop -- [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See `Form` documentation for the [experimental_customMergeAllOf](./api-reference/form-props.md#experimental_customMergeAllOf) prop +- [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See `Form` documentation for the [experimental_customMergeAllOf](./api-reference/form-props.md#experimental_customMergeAllOf) prop #### Returns diff --git a/packages/utils/test/mergeDefaultsWithFormData.test.ts b/packages/utils/test/mergeDefaultsWithFormData.test.ts index a63f93c686..8ccf2dcb64 100644 --- a/packages/utils/test/mergeDefaultsWithFormData.test.ts +++ b/packages/utils/test/mergeDefaultsWithFormData.test.ts @@ -25,6 +25,10 @@ describe('mergeDefaultsWithFormData()', () => { expect(mergeDefaultsWithFormData({}, undefined, undefined, true)).toEqual({}); }); + it('should return default when formData is null and defaultSupercedesUndefined true', () => { + expect(mergeDefaultsWithFormData({}, null, undefined, true)).toBeNull(); + }); + it('should return undefined when formData is undefined', () => { expect(mergeDefaultsWithFormData(undefined, undefined)).toBeUndefined(); }); From ca602ab65126b4861a13fc66e3072640e09601f9 Mon Sep 17 00:00:00 2001 From: Heath Chiavettone Date: Mon, 21 Oct 2024 09:43:41 -0700 Subject: [PATCH 6/8] - Fixed broken links --- packages/docs/docs/api-reference/utility-functions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docs/docs/api-reference/utility-functions.md b/packages/docs/docs/api-reference/utility-functions.md index ae839549aa..a6b0455234 100644 --- a/packages/docs/docs/api-reference/utility-functions.md +++ b/packages/docs/docs/api-reference/utility-functions.md @@ -898,8 +898,8 @@ Returns the superset of `formData` that includes the given set updated to includ - [formData]: T | undefined - The current formData, if any, onto which to provide any missing defaults - [rootSchema]: S | undefined - The root schema, used to primarily to look up `$ref`s - [includeUndefinedValues=false]: boolean | "excludeObjectChildren" - Optional flag, if true, cause undefined values to be added as defaults. If "excludeObjectChildren", cause undefined values for this object and pass `includeUndefinedValues` as false when computing defaults for any nested object properties. -- [experimental_defaultFormStateBehavior]: Experimental_DefaultFormStateBehavior - See `Form` documentation for the [experimental_defaultFormStateBehavior](./api-reference/form-props.md#experimental_defaultFormStateBehavior) prop -- [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See `Form` documentation for the [experimental_customMergeAllOf](./api-reference/form-props.md#experimental_customMergeAllOf) prop +- [experimental_defaultFormStateBehavior]: Experimental_DefaultFormStateBehavior - See `Form` documentation for the [experimental_defaultFormStateBehavior](./form-props.md#experimental_defaultFormStateBehavior) prop +- [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See `Form` documentation for the [experimental_customMergeAllOf](./form-props.md#experimental_customMergeAllOf) prop #### Returns From 16f08ea11cdff8aa91b9ff02595ba4a625ba60b0 Mon Sep 17 00:00:00 2001 From: Heath Chiavettone Date: Mon, 21 Oct 2024 10:04:08 -0700 Subject: [PATCH 7/8] - Added section header for wrapping BaseInputTemplate --- packages/docs/docs/advanced-customization/custom-templates.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/docs/docs/advanced-customization/custom-templates.md b/packages/docs/docs/advanced-customization/custom-templates.md index cc0393fd82..6491efbb5c 100644 --- a/packages/docs/docs/advanced-customization/custom-templates.md +++ b/packages/docs/docs/advanced-customization/custom-templates.md @@ -362,6 +362,8 @@ render( ); ``` +### Wrapping BaseInputTemplate to customize it + Sometimes you just need to pass some additional properties to the existing `BaseInputTemplate`. The way to do this varies based upon whether you are using `core` or some other theme (such as `mui`): From 3f33fe3a0275c5ac355a90f8ac0179eee8dec1f8 Mon Sep 17 00:00:00 2001 From: Heath Chiavettone Date: Mon, 21 Oct 2024 10:05:43 -0700 Subject: [PATCH 8/8] - Updated CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a06c0f81e..0735abc61f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ should change the heading of the (upcoming) version to include a major version b - Updated the `form-props.md` to add documentation for the new `experimental_customMergeAllOf` props and the `experimental_defaultFormStateBehavior.mergeDefaultsIntoFormData` option - Updated the `utility-functions.md` to add documentation for the new optional `defaultSupercedesUndefined` parameter and the two missing optional fields on `getDefaultFormState()` +- Updated the `custom-templates.md` to add a section header for wrapping `BaseInputTemplate` - Updated the playground to add controls for the new `mergeDefaultsIntoFormData` option - In the process, moved the `Show Error List` component over one column, making it inline radio buttons rather than a select