Skip to content

Commit 5071361

Browse files
foyarashnickgrosheath-freenome
authored
fix(utils): default value for defaults as objects (#4637)
* fix(utils): default value for defaults as objects * Update CHANGELOG.md --------- Co-authored-by: Nick Grosenbacher <[email protected]> Co-authored-by: Heath C <[email protected]>
1 parent c05dbc1 commit 5071361

File tree

4 files changed

+61
-1
lines changed

4 files changed

+61
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ should change the heading of the (upcoming) version to include a major version b
2121
## @rjsf/utils
2222

2323
- Fixed issue where oneOf radio button could not be modified when defaults were set, fixing [#4634](https://github.com/rjsf-team/react-jsonschema-form/issues/4634)
24+
- Fix default value for object properties such as enums that are rendered in select, radio inputs, etc.
2425

2526
# 6.0.0-beta.10
2627

packages/utils/src/mergeDefaultsWithFormData.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,22 @@ export default function mergeDefaultsWithFormData<T = any>(
6767
const keyValue = get(formData, key);
6868
const keyExistsInDefaults = isObject(defaults) && key in (defaults as GenericObjectType);
6969
const keyExistsInFormData = key in (formData as GenericObjectType);
70+
const keyDefault = get(defaults, key) ?? {};
71+
const defaultValueIsNestedObject = keyExistsInDefaults && Object.entries(keyDefault).some(([, v]) => isObject(v));
72+
73+
const keyDefaultIsObject = keyExistsInDefaults && isObject(get(defaults, key));
74+
const keyHasFormDataObject = keyExistsInFormData && isObject(keyValue);
75+
76+
if (keyDefaultIsObject && keyHasFormDataObject && !defaultValueIsNestedObject) {
77+
acc[key as keyof T] = {
78+
...get(defaults, key),
79+
...keyValue,
80+
};
81+
return acc;
82+
}
83+
7084
acc[key as keyof T] = mergeDefaultsWithFormData<T>(
71-
defaults ? get(defaults, key) : {},
85+
get(defaults, key) ?? {},
7286
keyValue,
7387
mergeExtraArrayDefaults,
7488
defaultSupercedesUndefined,

packages/utils/src/schema/getDefaultFormState.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,13 @@ export default function getDefaultFormState<
728728
shouldMergeDefaultsIntoFormData: true,
729729
});
730730

731+
if (schema.type !== 'object' && isObject(schema.default)) {
732+
return {
733+
...defaults,
734+
...formData,
735+
} as T;
736+
}
737+
731738
// If the formData is an object or an array, add additional properties from formData and override formData with
732739
// defaults since the defaults are already merged with formData.
733740
if (isObject(formData) || Array.isArray(formData)) {

packages/utils/test/schema/getDefaultFormStateTest.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,6 +1342,28 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType
13421342
});
13431343
});
13441344

1345+
describe('an object with a valid formData and enum property with default value', () => {
1346+
test('getDefaultFormState', () => {
1347+
const schema: RJSFSchema = {
1348+
type: 'object',
1349+
properties: {
1350+
test: {
1351+
type: 'string',
1352+
enum: [
1353+
{ label: 'a', value: 'a' },
1354+
{ label: 'b', value: 'b' },
1355+
],
1356+
default: { label: 'a', value: 'a' },
1357+
},
1358+
},
1359+
};
1360+
1361+
expect(getDefaultFormState(testValidator, schema, { test: { label: 'b', value: 'b' } })).toEqual({
1362+
test: { label: 'b', value: 'b' },
1363+
});
1364+
});
1365+
});
1366+
13451367
describe('oneOf with const values', () => {
13461368
const schema: RJSFSchema = {
13471369
type: 'object',
@@ -1970,6 +1992,22 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType
19701992

19711993
expect(ensureFormDataMatchingSchema(testValidator, schema, schema, 'a')).toEqual('a');
19721994
});
1995+
1996+
it('Test schema with valid formData with an enum and its default value', () => {
1997+
schema = {
1998+
type: 'string',
1999+
enum: [
2000+
{ label: 'a', value: 'a' },
2001+
{ label: 'b', value: 'b' },
2002+
],
2003+
default: { label: 'a', value: 'a' },
2004+
};
2005+
2006+
expect(getDefaultFormState(testValidator, schema, { label: 'b', value: 'b' })).toEqual({
2007+
label: 'b',
2008+
value: 'b',
2009+
});
2010+
});
19732011
});
19742012
describe('AJV $data reference in const property in schema should not be treated as default/const value', () => {
19752013
let schema: RJSFSchema;

0 commit comments

Comments
 (0)