Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ should change the heading of the (upcoming) version to include a major version b

# 5.22.4

## @rjsf/utils

- Fixed issue with array schema defaults not applying properly when formData is an empty array, fixing [#4335](https://github.com/rjsf-team/react-jsonschema-form/issues/4335).

## Dev / docs / playground

- Fix issue 'Maximum call stack size exceeded' with playground share with large content.
Expand All @@ -26,7 +30,7 @@ should change the heading of the (upcoming) version to include a major version b

## @rjsf/utils

- Fixed deep nested dependencies issue with assigning values to formData, fixing [[#4334](https://github.com/rjsf-team/react-jsonschema-form/issues/4334)]
- Fixed deep nested dependencies issue with assigning values to formData, fixing [#4334](https://github.com/rjsf-team/react-jsonschema-form/issues/4334)

# 5.22.2

Expand Down
2 changes: 1 addition & 1 deletion packages/docs/docs/api-reference/form-props.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ render(
schema={schema}
validator={validator}
experimental_defaultFormStateBehavior={{
arrayMinItems: { populate: 'requiredOnly' },
emptyObjectFields: 'populateRequiredDefaults',
}}
/>,
document.getElementById('app')
Expand Down
18 changes: 13 additions & 5 deletions packages/utils/src/schema/getDefaultFormState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,11 +432,14 @@ export function getArrayDefaults<T = any, S extends StrictRJSFSchema = RJSFSchem
): T | T[] | undefined {
const schema: S = rawSchema;

const neverPopulate = experimental_defaultFormStateBehavior?.arrayMinItems?.populate === 'never';
const ignoreMinItemsFlagSet = experimental_defaultFormStateBehavior?.arrayMinItems?.populate === 'requiredOnly';
const arrayMinItemsStateBehavior = experimental_defaultFormStateBehavior?.arrayMinItems ?? {};
const { populate: arrayMinItemsPopulate, mergeExtraDefaults: arrayMergeExtraDefaults } = arrayMinItemsStateBehavior;

const neverPopulate = arrayMinItemsPopulate === 'never';
const ignoreMinItemsFlagSet = arrayMinItemsPopulate === 'requiredOnly';
const isPopulateAll = arrayMinItemsPopulate === 'all' || (!neverPopulate && !ignoreMinItemsFlagSet);
const computeSkipPopulate = arrayMinItemsStateBehavior?.computeSkipPopulate ?? (() => false);
const isSkipEmptyDefaults = experimental_defaultFormStateBehavior?.emptyObjectFields === 'skipEmptyDefaults';
const computeSkipPopulate =
experimental_defaultFormStateBehavior?.arrayMinItems?.computeSkipPopulate ?? (() => false);

const emptyDefault = isSkipEmptyDefaults ? undefined : [];

Expand All @@ -460,7 +463,7 @@ export function getArrayDefaults<T = any, S extends StrictRJSFSchema = RJSFSchem
if (neverPopulate) {
defaults = rawFormData;
} else {
defaults = rawFormData.map((item: T, idx: number) => {
const itemDefaults = rawFormData.map((item: T, idx: number) => {
return computeDefaults<T, S, F>(validator, schemaItem, {
rootSchema,
_recurseList,
Expand All @@ -470,6 +473,11 @@ export function getArrayDefaults<T = any, S extends StrictRJSFSchema = RJSFSchem
required,
});
}) as T[];

// If the populate 'requiredOnly' flag is set then we only merge and include extra defaults if they are required.
// Or if populate 'all' is set we merge and include extra defaults.
const mergeExtraDefaults = ((ignoreMinItemsFlagSet && required) || isPopulateAll) && arrayMergeExtraDefaults;
defaults = mergeDefaultsWithFormData(defaults, itemDefaults, mergeExtraDefaults);
}
}

Expand Down
43 changes: 43 additions & 0 deletions packages/utils/test/schema/getDefaultFormStateTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,49 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType
},
});
});
it('test an array with defaults with no formData', () => {
const schema: RJSFSchema = {
type: 'array',
minItems: 4,
default: ['Raphael', 'Michaelangelo'],
items: {
type: 'string',
default: 'Unknown',
},
};

expect(
computeDefaults(testValidator, schema, {
rootSchema: schema,
includeUndefinedValues: 'excludeObjectChildren',
})
).toEqual(['Raphael', 'Michaelangelo', 'Unknown', 'Unknown']);
});
it('test an array with defaults with empty array as formData', () => {
const schema: RJSFSchema = {
type: 'array',
minItems: 4,
default: ['Raphael', 'Michaelangelo'],
items: {
type: 'string',
default: 'Unknown',
},
};

expect(
computeDefaults(testValidator, schema, {
rootSchema: schema,
rawFormData: [],
includeUndefinedValues: 'excludeObjectChildren',
experimental_defaultFormStateBehavior: {
arrayMinItems: {
mergeExtraDefaults: true,
populate: 'all',
},
},
})
).toEqual(['Raphael', 'Michaelangelo', 'Unknown', 'Unknown']);
});
it('test computeDefaults handles an invalid property schema', () => {
const schema: RJSFSchema = {
type: 'object',
Expand Down