From 119bfc94b2d6db54f2bd4446408b9f62c2215767 Mon Sep 17 00:00:00 2001 From: Piotr-Debicki <105816286+Piotr-Debicki@users.noreply.github.com> Date: Tue, 4 Feb 2025 16:49:59 -0500 Subject: [PATCH 01/10] fix additional property defaults not generating --- packages/core/src/components/Form.tsx | 13 ++++++++++++- packages/utils/src/createSchemaUtils.ts | 3 +++ packages/utils/src/schema/getDefaultFormState.ts | 15 ++++++++++++++- packages/validator-ajv6/src/validator.ts | 2 +- .../src/processRawValidationErrors.ts | 2 +- 5 files changed, 31 insertions(+), 4 deletions(-) diff --git a/packages/core/src/components/Form.tsx b/packages/core/src/components/Form.tsx index 5a5d7a800c..a02df1a11c 100644 --- a/packages/core/src/components/Form.tsx +++ b/packages/core/src/components/Form.tsx @@ -252,6 +252,8 @@ export interface FormState( @@ -118,6 +120,7 @@ class SchemaUtils * The formData should take precedence unless it's not valid. This is useful when for example the value from formData does not exist in the schema 'enum' property, in such cases we take the value from the defaults because the value from the formData is not valid. */ shouldMergeDefaultsIntoFormData?: boolean; + /** Optional flag, if true, indicates that defaults have already been generated */ + initDefaultsGenerated?: boolean; } /** Computes the defaults for the current `schema` given the `rawFormData` and `parentDefaults` if any. This drills into @@ -203,6 +205,7 @@ export function computeDefaults = {}, defaults?: T | T[] | undefined ): T { @@ -452,6 +457,7 @@ export function getObjectDefaults( acc, @@ -467,7 +473,7 @@ export function getObjectDefaults( @@ -532,6 +539,7 @@ export function getArrayDefaults = {}, defaults?: T | T[] | undefined ): T | T[] | undefined { @@ -560,6 +568,7 @@ export function getArrayDefaults @@ -706,6 +718,7 @@ export default function getDefaultFormState< experimental_customMergeAllOf, rawFormData: formData, shouldMergeDefaultsIntoFormData: true, + initDefaultsGenerated, }); // If the formData is an object or an array, add additional properties from formData and override formData with diff --git a/packages/validator-ajv6/src/validator.ts b/packages/validator-ajv6/src/validator.ts index 79c221a246..5b8f0bcd6b 100644 --- a/packages/validator-ajv6/src/validator.ts +++ b/packages/validator-ajv6/src/validator.ts @@ -152,7 +152,7 @@ export default class AJV6Validator(this, schema, formData, rootSchema, true) as T; + const newFormData = getDefaultFormState(this, schema, formData, rootSchema, false, true) as T; const errorHandler = customValidate(newFormData, createErrorHandler(newFormData), uiSchema); const userErrorSchema = unwrapErrorHandler(errorHandler); diff --git a/packages/validator-ajv8/src/processRawValidationErrors.ts b/packages/validator-ajv8/src/processRawValidationErrors.ts index 52dfc29913..0c0d22b591 100644 --- a/packages/validator-ajv8/src/processRawValidationErrors.ts +++ b/packages/validator-ajv8/src/processRawValidationErrors.ts @@ -150,7 +150,7 @@ export default function processRawValidationErrors< } // Include form data with undefined values, which is required for custom validation. - const newFormData = getDefaultFormState(validator, schema, formData, schema, true) as T; + const newFormData = getDefaultFormState(validator, schema, formData, schema, false, true) as T; const errorHandler = customValidate(newFormData, createErrorHandler(newFormData), uiSchema); const userErrorSchema = unwrapErrorHandler(errorHandler); From a9497a620b0dd650edd99b68531719029c22ad20 Mon Sep 17 00:00:00 2001 From: Piotr-Debicki <105816286+Piotr-Debicki@users.noreply.github.com> Date: Wed, 5 Feb 2025 14:14:06 -0500 Subject: [PATCH 02/10] update tests --- .../components/fields/MultiSchemaField.tsx | 2 +- packages/utils/src/types.ts | 1 + .../test/schema/getDefaultFormStateTest.ts | 53 +++++++++++-------- 3 files changed, 33 insertions(+), 23 deletions(-) diff --git a/packages/core/src/components/fields/MultiSchemaField.tsx b/packages/core/src/components/fields/MultiSchemaField.tsx index 498713038c..db4b38649e 100644 --- a/packages/core/src/components/fields/MultiSchemaField.tsx +++ b/packages/core/src/components/fields/MultiSchemaField.tsx @@ -126,7 +126,7 @@ class AnyOfField { diff --git a/packages/utils/src/types.ts b/packages/utils/src/types.ts index 2d6c8335c3..5ba6d1ded8 100644 --- a/packages/utils/src/types.ts +++ b/packages/utils/src/types.ts @@ -1082,6 +1082,7 @@ export interface SchemaUtilsType { - expect(getDefaultFormState(testValidator, schema, undefined, schema, includeUndefinedValues)).toEqual( + expect(getDefaultFormState(testValidator, schema, undefined, schema, false, includeUndefinedValues)).toEqual( expected ); }); @@ -458,7 +459,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType }; test('getDefaultFormState', () => { - expect(getDefaultFormState(testValidator, schema, undefined, schema, includeUndefinedValues)).toEqual( + expect(getDefaultFormState(testValidator, schema, undefined, schema, false, includeUndefinedValues)).toEqual( expected ); }); @@ -794,7 +795,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType test('getDefaultFormState', () => { expect( - getDefaultFormState(testValidator, schema, rawFormData, schema, false, { + getDefaultFormState(testValidator, schema, rawFormData, schema, false, false, { emptyObjectFields: 'populateAllDefaults', allOf: 'skipDefaults', arrayMinItems: { @@ -873,9 +874,9 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType const expected = {}; test('getDefaultFormState', () => { - expect(getDefaultFormState(testValidator, schema, undefined, schema, includeUndefinedValues)).toEqual( - expected - ); + expect( + getDefaultFormState(testValidator, schema, undefined, schema, false, includeUndefinedValues) + ).toEqual(expected); }); test('computeDefaults', () => { @@ -1050,6 +1051,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType rawFormData, schema, includeUndefinedValues, + false, experimental_defaultFormStateBehavior ) ).toEqual({ @@ -1131,6 +1133,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType rawFormData, schema, includeUndefinedValues, + false, experimental_defaultFormStateBehavior ) ).toEqual({ @@ -1298,6 +1301,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType rawFormData, schema, undefined, + false, experimental_defaultFormStateBehavior ) ).toEqual(expected); @@ -1380,6 +1384,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType undefined, schema, undefined, + false, experimental_defaultFormStateBehavior ) ).toEqual(expected); @@ -1427,6 +1432,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType undefined, schema, undefined, + false, experimental_defaultFormStateBehavior ) ).toEqual(expected); @@ -1474,6 +1480,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType undefined, schema, undefined, + false, experimental_defaultFormStateBehavior ) ).toEqual(expected); @@ -1536,6 +1543,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType rawFormData, schema, undefined, + false, experimental_defaultFormStateBehavior ) ).toEqual(expected); @@ -1588,7 +1596,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType const expected = ['Raphael', 'Michaelangelo', 'Unknown', 'Unknown']; test('getDefaultFormState', () => { - expect(getDefaultFormState(testValidator, schema, undefined, schema, includeUndefinedValues)).toEqual( + expect(getDefaultFormState(testValidator, schema, undefined, schema, false, includeUndefinedValues)).toEqual( expected ); }); @@ -1647,6 +1655,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType schema, undefined, schema, + false, includeUndefinedValues, experimental_defaultFormStateBehavior ) @@ -1710,7 +1719,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType const expected: undefined[] = [undefined, undefined, undefined, undefined]; test('getDefaultFormState', () => { - expect(getDefaultFormState(testValidator, schema, undefined, schema, includeUndefinedValues)).toEqual( + expect(getDefaultFormState(testValidator, schema, undefined, schema, false, includeUndefinedValues)).toEqual( expected ); }); @@ -1757,7 +1766,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType const expected = ['ConstFromRoot', 'ConstFromRoot', 'Constant', 'Constant']; test('getDefaultFormState', () => { - expect(getDefaultFormState(testValidator, schema, undefined, schema, includeUndefinedValues)).toEqual( + expect(getDefaultFormState(testValidator, schema, undefined, schema, false, includeUndefinedValues)).toEqual( expected ); }); @@ -1809,7 +1818,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType const expected: never[] = []; test('getDefaultFormState', () => { - expect(getDefaultFormState(testValidator, schema, undefined, schema, includeUndefinedValues)).toEqual( + expect(getDefaultFormState(testValidator, schema, undefined, schema, false, includeUndefinedValues)).toEqual( expected ); }); @@ -3855,7 +3864,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType }, }; expect( - getDefaultFormState(testValidator, schema, {}, undefined, undefined, { + getDefaultFormState(testValidator, schema, {}, undefined, undefined, false, { emptyObjectFields: 'populateRequiredDefaults', }) ).toEqual({ name: {} }); @@ -3886,7 +3895,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType }, }; expect( - getDefaultFormState(testValidator, schema, {}, undefined, undefined, { + getDefaultFormState(testValidator, schema, {}, undefined, undefined, false, { emptyObjectFields: 'populateRequiredDefaults', }) ).toEqual({ @@ -3920,7 +3929,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType ], }; expect( - getDefaultFormState(testValidator, schema, {}, undefined, undefined, { + getDefaultFormState(testValidator, schema, {}, undefined, undefined, false, { emptyObjectFields: 'populateRequiredDefaults', }) ).toEqual({ foo: 'fooVal', baz: 'bazIsRequired' }); @@ -4052,7 +4061,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType }, }; expect( - getDefaultFormState(testValidator, schema, {}, undefined, undefined, { + getDefaultFormState(testValidator, schema, {}, undefined, undefined, false, { emptyObjectFields: 'populateRequiredDefaults', }) ).toEqual({ name: {} }); @@ -4083,7 +4092,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType }, }; expect( - getDefaultFormState(testValidator, schema, {}, undefined, undefined, { + getDefaultFormState(testValidator, schema, {}, undefined, undefined, false, { emptyObjectFields: 'populateRequiredDefaults', }) ).toEqual({ @@ -4117,7 +4126,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType ], }; expect( - getDefaultFormState(testValidator, schema, {}, undefined, undefined, { + getDefaultFormState(testValidator, schema, {}, undefined, undefined, false, { emptyObjectFields: 'populateRequiredDefaults', }) ).toEqual({ foo: 'fooVal', baz: 'bazIsRequired' }); @@ -4635,7 +4644,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType 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, { + getDefaultFormState(testValidator, schema, formData, undefined, undefined, false, { mergeDefaultsIntoFormData: 'useDefaultIfFormDataUndefined', }) ).toEqual(defaultedFormData); @@ -4683,7 +4692,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType }, }; expect( - getDefaultFormState(testValidator, schema, { requiredArray: ['raw0'] }, schema, false, { + getDefaultFormState(testValidator, schema, { requiredArray: ['raw0'] }, schema, false, false, { arrayMinItems: { mergeExtraDefaults: true }, }) ).toEqual({ @@ -4703,7 +4712,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType required: ['requiredArray'], }; expect( - getDefaultFormState(testValidator, schema, undefined, schema, false, { + getDefaultFormState(testValidator, schema, undefined, schema, false, false, { arrayMinItems: { populate: 'requiredOnly' }, }) ).toEqual({ requiredArray: ['default0', 'default0'] }); @@ -4721,7 +4730,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType required: ['requiredArray'], }; expect( - getDefaultFormState(testValidator, schema, { requiredArray: ['raw0'] }, schema, false, { + getDefaultFormState(testValidator, schema, { requiredArray: ['raw0'] }, schema, false, false, { arrayMinItems: { populate: 'requiredOnly' }, }) ).toEqual({ requiredArray: ['raw0'] }); @@ -4739,7 +4748,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType required: ['requiredArray'], }; expect( - getDefaultFormState(testValidator, schema, { requiredArray: ['raw0'] }, schema, false, { + getDefaultFormState(testValidator, schema, { requiredArray: ['raw0'] }, schema, false, false, { arrayMinItems: { populate: 'requiredOnly', mergeExtraDefaults: true }, }) ).toEqual({ requiredArray: ['raw0', 'default0'] }); @@ -4762,7 +4771,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType required: ['stringArray', 'numberArray'], }; expect( - getDefaultFormState(testValidator, schema, {}, schema, false, { + getDefaultFormState(testValidator, schema, {}, schema, false, false, { arrayMinItems: { computeSkipPopulate: (_, schema) => !Array.isArray(schema?.items) && typeof schema?.items !== 'boolean' && schema?.items?.type === 'number', From 395d06651eed13d24fd498fee0cc130c2b460579 Mon Sep 17 00:00:00 2001 From: Piotr-Debicki <105816286+Piotr-Debicki@users.noreply.github.com> Date: Wed, 5 Feb 2025 14:38:37 -0500 Subject: [PATCH 03/10] update descriptions, rm log --- packages/core/src/components/Form.tsx | 7 ------- packages/utils/src/createSchemaUtils.ts | 2 +- packages/utils/src/schema/getDefaultFormState.ts | 3 ++- packages/utils/src/types.ts | 1 + 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/packages/core/src/components/Form.tsx b/packages/core/src/components/Form.tsx index a02df1a11c..07f18fb2f1 100644 --- a/packages/core/src/components/Form.tsx +++ b/packages/core/src/components/Form.tsx @@ -426,13 +426,6 @@ export default class Form< ); } - if (schema.title === 'console') { - console.log('schema', schema); - console.log('retrievedSchema', retrievedSchema); - console.log('edit', edit); - console.log('props', props); - } - const formData: T = schemaUtils.getDefaultFormState(schema, inputFormData, state.initialDefaultsGenerated) as T; const _retrievedSchema = this.updateRetrievedSchema( retrievedSchema ?? schemaUtils.retrieveSchema(schema, formData) diff --git a/packages/utils/src/createSchemaUtils.ts b/packages/utils/src/createSchemaUtils.ts index e5c91c3043..709bfbe418 100644 --- a/packages/utils/src/createSchemaUtils.ts +++ b/packages/utils/src/createSchemaUtils.ts @@ -103,7 +103,7 @@ class SchemaUtils * The formData should take precedence unless it's not valid. This is useful when for example the value from formData does not exist in the schema 'enum' property, in such cases we take the value from the defaults because the value from the formData is not valid. */ shouldMergeDefaultsIntoFormData?: boolean; - /** Optional flag, if true, indicates that defaults have already been generated */ + /** Indicates whether or not initial defaults have been generated */ initDefaultsGenerated?: boolean; } @@ -682,6 +682,7 @@ export function getDefaultBasedOnSchemaType< * @param theSchema - The schema for which the default state is desired * @param [formData] - The current formData, if any, onto which to provide any missing defaults * @param [rootSchema] - The root schema, used to primarily to look up `$ref`s + * @param initDefaultsGenerated - indicates whether or not initial defaults have been generated * @param [includeUndefinedValues=false] - 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. diff --git a/packages/utils/src/types.ts b/packages/utils/src/types.ts index 5ba6d1ded8..164cfe034d 100644 --- a/packages/utils/src/types.ts +++ b/packages/utils/src/types.ts @@ -1074,6 +1074,7 @@ export interface SchemaUtilsType Date: Wed, 5 Feb 2025 14:50:53 -0500 Subject: [PATCH 04/10] fix core form tests --- packages/core/test/Form.test.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/core/test/Form.test.jsx b/packages/core/test/Form.test.jsx index b774049fd9..d3872d3d94 100644 --- a/packages/core/test/Form.test.jsx +++ b/packages/core/test/Form.test.jsx @@ -147,6 +147,7 @@ describeRepeated('Form common', (createFormComponent) => { schemaValidationErrorSchema: undefined, schemaUtils: sinon.match.object, retrievedSchema: schema, + initialDefaultsGenerated: true, }); }); }); @@ -1512,6 +1513,7 @@ describeRepeated('Form common', (createFormComponent) => { schemaValidationErrorSchema: undefined, schemaUtils: sinon.match.object, retrievedSchema: formProps.schema, + initialDefaultsGenerated: true, }); }); }); From adb0597cc36146e39be06c8cb33bd6e4d6435963 Mon Sep 17 00:00:00 2001 From: Piotr-Debicki <105816286+Piotr-Debicki@users.noreply.github.com> Date: Wed, 5 Feb 2025 17:30:00 -0500 Subject: [PATCH 05/10] add object additionalProperties defaults test --- packages/core/test/ObjectField.test.jsx | 159 ++++++++++++++++++++++++ 1 file changed, 159 insertions(+) diff --git a/packages/core/test/ObjectField.test.jsx b/packages/core/test/ObjectField.test.jsx index 5bc7ec8a5d..2ce3d18dff 100644 --- a/packages/core/test/ObjectField.test.jsx +++ b/packages/core/test/ObjectField.test.jsx @@ -1142,6 +1142,165 @@ describe('ObjectField', () => { }); }); + it('should generate the specifed default key and value inputs if default is provided outside of additionalProperties schema', () => { + const customSchema = { + ...schema, + default: { + defaultKey: 'defaultValue', + }, + }; + const { onChange } = createFormComponent({ + schema: customSchema, + formData: {}, + }); + + sinon.assert.calledWithMatch(onChange.lastCall, { + formData: { + defaultKey: 'defaultValue', + }, + }); + }); + + it('should generate the specifed default key/value input with custom formData provided', () => { + const customSchema = { + ...schema, + default: { + defaultKey: 'defaultValue', + }, + }; + const { onChange } = createFormComponent({ + schema: customSchema, + formData: { + someData: 'someValue', + }, + }); + + sinon.assert.calledWithMatch(onChange.lastCall, { + formData: { + defaultKey: 'defaultValue', + someData: 'someValue', + }, + }); + }); + + it('should edit the specifed default key without duplicating', () => { + const customSchema = { + ...schema, + default: { + defaultKey: 'defaultValue', + }, + }; + const { node, onChange } = createFormComponent({ + schema: customSchema, + formData: {}, + }); + + fireEvent.blur(node.querySelector('#root_defaultKey-key'), { target: { value: 'newDefaultKey' } }); + + sinon.assert.calledWithMatch(onChange.lastCall, { + formData: { + newDefaultKey: 'defaultValue', + }, + }); + }); + + it('should remove the specifed default key/value input item', () => { + const customSchema = { + ...schema, + default: { + defaultKey: 'defaultValue', + }, + }; + const { node, onChange } = createFormComponent({ + schema: customSchema, + formData: {}, + }); + + fireEvent.click(node.querySelector('.array-item-remove')); + + sinon.assert.calledWithMatch(onChange.lastCall, { + formData: {}, + }); + }); + + it('should handle nested additional property default key/value input generation', () => { + const customSchema = { + ...schema, + default: { + defaultKey: 'defaultValue', + }, + properties: { + nested: { + type: 'object', + properties: { + bar: { + type: 'object', + additionalProperties: { + type: 'string', + }, + default: { + baz: 'value', + }, + }, + }, + }, + }, + }; + + const { onChange } = createFormComponent({ + schema: customSchema, + formData: {}, + }); + + sinon.assert.calledWithMatch(onChange.lastCall, { + formData: { + defaultKey: 'defaultValue', + nested: { + bar: { + baz: 'value', + }, + }, + }, + }); + }); + + it('should remove nested additional property default key/value input', () => { + const customSchema = { + ...schema, + properties: { + nested: { + type: 'object', + properties: { + bar: { + type: 'object', + additionalProperties: { + type: 'string', + }, + default: { + baz: 'value', + }, + }, + }, + }, + }, + }; + + const { node, onChange } = createFormComponent({ + schema: customSchema, + formData: {}, + }); + + fireEvent.click(node.querySelector('.array-item-remove')); + + sinon.assert.calledWithMatch(onChange.lastCall, { + formData: { + nested: { + bar: {}, + }, + }, + }); + }); + it('should not provide an expand button if length equals maxProperties', () => { const { node } = createFormComponent({ schema: { maxProperties: 1, ...schema }, From 06255abbf0e439c6656e3d3fa58e0f4aa205c3f9 Mon Sep 17 00:00:00 2001 From: Piotr-Debicki <105816286+Piotr-Debicki@users.noreply.github.com> Date: Wed, 5 Feb 2025 19:05:07 -0500 Subject: [PATCH 06/10] fix verbiage --- packages/core/test/ObjectField.test.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/test/ObjectField.test.jsx b/packages/core/test/ObjectField.test.jsx index 2ce3d18dff..b20a63aeed 100644 --- a/packages/core/test/ObjectField.test.jsx +++ b/packages/core/test/ObjectField.test.jsx @@ -1142,7 +1142,7 @@ describe('ObjectField', () => { }); }); - it('should generate the specifed default key and value inputs if default is provided outside of additionalProperties schema', () => { + it('should generate the specified default key and value inputs if default is provided outside of additionalProperties schema', () => { const customSchema = { ...schema, default: { @@ -1161,7 +1161,7 @@ describe('ObjectField', () => { }); }); - it('should generate the specifed default key/value input with custom formData provided', () => { + it('should generate the specified default key/value input with custom formData provided', () => { const customSchema = { ...schema, default: { @@ -1183,7 +1183,7 @@ describe('ObjectField', () => { }); }); - it('should edit the specifed default key without duplicating', () => { + it('should edit the specified default key without duplicating', () => { const customSchema = { ...schema, default: { @@ -1204,7 +1204,7 @@ describe('ObjectField', () => { }); }); - it('should remove the specifed default key/value input item', () => { + it('should remove the specified default key/value input item', () => { const customSchema = { ...schema, default: { From 6b1354a1caeb8a325701a4eb3b2b36615e59d8a3 Mon Sep 17 00:00:00 2001 From: Piotr-Debicki <105816286+Piotr-Debicki@users.noreply.github.com> Date: Fri, 7 Feb 2025 13:33:09 -0500 Subject: [PATCH 07/10] allow regeneration of additional property defaults on reset --- packages/core/src/components/Form.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/src/components/Form.tsx b/packages/core/src/components/Form.tsx index 07f18fb2f1..f42130ed16 100644 --- a/packages/core/src/components/Form.tsx +++ b/packages/core/src/components/Form.tsx @@ -761,6 +761,7 @@ export default class Form< errors: [] as unknown, schemaValidationErrors: [] as unknown, schemaValidationErrorSchema: {}, + initialDefaultsGenerated: false, } as FormState; this.setState(state, () => onChange && onChange({ ...this.state, ...state })); From a0e64aa4f4646c8f3a15a3569a92e82c97fe532d Mon Sep 17 00:00:00 2001 From: Piotr-Debicki <105816286+Piotr-Debicki@users.noreply.github.com> Date: Fri, 7 Feb 2025 15:56:27 -0500 Subject: [PATCH 08/10] update verbiage & docs --- packages/core/src/components/Form.tsx | 2 +- .../docs/api-reference/utility-functions.md | 1 + packages/utils/src/createSchemaUtils.ts | 6 ++-- .../utils/src/schema/getDefaultFormState.ts | 30 +++++++++---------- packages/utils/src/types.ts | 4 +-- 5 files changed, 22 insertions(+), 21 deletions(-) diff --git a/packages/core/src/components/Form.tsx b/packages/core/src/components/Form.tsx index f42130ed16..37979dfd57 100644 --- a/packages/core/src/components/Form.tsx +++ b/packages/core/src/components/Form.tsx @@ -252,7 +252,7 @@ export interface FormState( @@ -120,7 +120,7 @@ class SchemaUtils * The formData should take precedence unless it's not valid. This is useful when for example the value from formData does not exist in the schema 'enum' property, in such cases we take the value from the defaults because the value from the formData is not valid. */ shouldMergeDefaultsIntoFormData?: boolean; - /** Indicates whether or not initial defaults have been generated */ - initDefaultsGenerated?: boolean; + /** Indicates whether initial defaults have been generated */ + initialDefaultsGenerated?: boolean; } /** Computes the defaults for the current `schema` given the `rawFormData` and `parentDefaults` if any. This drills into @@ -205,7 +205,7 @@ export function computeDefaults = {}, defaults?: T | T[] | undefined ): T { @@ -457,7 +457,7 @@ export function getObjectDefaults( acc, @@ -473,7 +473,7 @@ export function getObjectDefaults( @@ -539,7 +539,7 @@ export function getArrayDefaults = {}, defaults?: T | T[] | undefined ): T | T[] | undefined { @@ -568,7 +568,7 @@ export function getArrayDefaults @@ -719,7 +719,7 @@ export default function getDefaultFormState< experimental_customMergeAllOf, rawFormData: formData, shouldMergeDefaultsIntoFormData: true, - initDefaultsGenerated, + initialDefaultsGenerated, }); // If the formData is an object or an array, add additional properties from formData and override formData with diff --git a/packages/utils/src/types.ts b/packages/utils/src/types.ts index 164cfe034d..7e73b9514a 100644 --- a/packages/utils/src/types.ts +++ b/packages/utils/src/types.ts @@ -1074,7 +1074,7 @@ export interface SchemaUtilsType Date: Fri, 7 Feb 2025 16:23:39 -0500 Subject: [PATCH 09/10] update CHANGELOG.md --- CHANGELOG.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b819d00e67..7f5cccb637 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,25 @@ it according to semantic versioning. For example, if your PR adds a breaking cha should change the heading of the (upcoming) version to include a major version bump. --> +# 5.24.4 + +## @rjsf/core + +- Added `initialDefaultsGenerated` flag to state, which indicates whether the initial generation of defaults has been completed +- Added `ObjectField` tests for additionalProperties with defaults + +## @rjsf/utils + +- Updated `getDefaultFormState` to add a new `initialDefaultsGenerated` prop flag, along with type definitions, fixing uneditable & permanent defaults with additional properties [3759](https://github.com/rjsf-team/react-jsonschema-form/issues/3759) +- Updated `createSchemaUtils` definition to reflect addition of `initialDefaultsGenerated` +- Updated existing tests where `getDefaultFormState` is used to reflect addition of `initialDefaultsGenerated` + +## @rjsf/docs +- Updated docs for `getDefaultFormState` to reflect addition of `initialDefaultsGenerated` prop + +## @rjsf/validator-ajv6 @rjsf/validator-avv8 +- Updated `getDefaultFormState` calls to reflect addition of `initialDefaultsGenerated` + # 5.24.3 ## @rjsf/utils From 8c400bc7af035f6dd50407ec4acc019d1845e905 Mon Sep 17 00:00:00 2001 From: Piotr-Debicki <105816286+Piotr-Debicki@users.noreply.github.com> Date: Mon, 10 Feb 2025 14:03:22 -0500 Subject: [PATCH 10/10] Update CHANGELOG.md Co-authored-by: Heath C <51679588+heath-freenome@users.noreply.github.com> --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f5cccb637..624a916211 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,12 @@ should change the heading of the (upcoming) version to include a major version b ## @rjsf/docs - Updated docs for `getDefaultFormState` to reflect addition of `initialDefaultsGenerated` prop -## @rjsf/validator-ajv6 @rjsf/validator-avv8 +## @rjsf/validator-ajv6 + +- Updated `getDefaultFormState` calls to reflect addition of `initialDefaultsGenerated` + +## @rjsf/validator-ajv8 + - Updated `getDefaultFormState` calls to reflect addition of `initialDefaultsGenerated` # 5.24.3