Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ should change the heading of the (upcoming) version to include a major version b

-->

# 5.24.0

## @rjsf/utils

- Fixed issue with assigning default values to formData with deeply nested required properties, fixing [#4399](https://github.com/rjsf-team/react-jsonschema-form/issues/4399)

# 5.23.2

## @rjsf/core
Expand Down
13 changes: 7 additions & 6 deletions packages/utils/src/schema/getDefaultFormState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,11 @@ function maybeAddDefaultToObject<T = any>(
// Or if the schema has a const property defined, then we should always return the computedDefault since it's coming from the const.
obj[key] = computedDefault;
} else if (emptyObjectFields !== 'skipDefaults') {
if (isObject(computedDefault)) {
// If isParentRequired is undefined, then we are at the root level of the schema so defer to the requiredness of
// the field key itself in the `requiredField` list
const isSelfOrParentRequired = isParentRequired === undefined ? requiredFields.includes(key) : isParentRequired;
// If isParentRequired is undefined, then we are at the root level of the schema so defer to the requiredness of
// the field key itself in the `requiredField` list
const isSelfOrParentRequired = isParentRequired === undefined ? requiredFields.includes(key) : isParentRequired;

if (isObject(computedDefault)) {
// If emptyObjectFields 'skipEmptyDefaults' store computedDefault if it's a non-empty object(e.g. not {})
if (emptyObjectFields === 'skipEmptyDefaults') {
if (!isEmpty(computedDefault)) {
Expand All @@ -138,11 +138,12 @@ function maybeAddDefaultToObject<T = any>(
} else if (
// Store computedDefault if it's a defined primitive (e.g., true) and satisfies certain conditions
// Condition 1: computedDefault is not undefined
// Condition 2: If emptyObjectFields is 'populateAllDefaults' or 'skipEmptyDefaults) or if the key is a required field
// Condition 2: If emptyObjectFields is 'populateAllDefaults' or 'skipEmptyDefaults)
// Or if isSelfOrParentRequired is 'true' and the key is a required field
computedDefault !== undefined &&
(emptyObjectFields === 'populateAllDefaults' ||
emptyObjectFields === 'skipEmptyDefaults' ||
requiredFields.includes(key))
(isSelfOrParentRequired && requiredFields.includes(key)))
) {
obj[key] = computedDefault;
}
Expand Down
42 changes: 42 additions & 0 deletions packages/utils/test/schema/getDefaultFormStateTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2284,6 +2284,48 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType
})
).toEqual({ requiredProperty: 'foo' });
});
it('test an object with a required property that has a nested optional property which has a nested required property with default', () => {
const schema: RJSFSchema = {
type: 'object',
properties: {
baseRequiredProperty: {
type: 'object',
properties: {
optionalProperty: {
type: 'object',
properties: {
nestedRequiredProperty: {
type: 'string',
default: '',
},
},
required: ['nestedRequiredProperty'],
},
requiredProperty: {
type: 'string',
default: 'foo',
},
},
required: ['requiredProperty'],
},
baseOptionalProperty: {
type: 'string',
default: 'baseOptionalProperty',
},
},
required: ['baseRequiredProperty'],
};
expect(
computeDefaults(testValidator, schema, {
rootSchema: schema,
experimental_defaultFormStateBehavior: { emptyObjectFields: 'populateRequiredDefaults' },
})
).toEqual({
baseRequiredProperty: {
requiredProperty: 'foo',
},
});
});
it('test an object with an optional property that has a nested required property and includeUndefinedValues', () => {
const schema: RJSFSchema = {
type: 'object',
Expand Down
Loading