Skip to content

Commit

Permalink
Fix: made small changes to utility functions to fix #3997 and #4322
Browse files Browse the repository at this point in the history
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
  • Loading branch information
heath-freenome committed Oct 5, 2024
1 parent b5ce52e commit 5db135a
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 6 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@ should change the heading of the (upcoming) version to include a major version b
-->

# 5.21.3

## @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

- 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

## @rjsf/core
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/components/fields/MultiSchemaField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,10 @@ class AnyOfField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends For
// so that only the root objects themselves are created without adding undefined children properties
newFormData = schemaUtils.getDefaultFormState(newOption, newFormData, 'excludeObjectChildren') as T;
}
onChange(newFormData, undefined, this.getFieldId());

this.setState({ selectedOption: intOption });
this.setState({ selectedOption: intOption }, () => {
onChange(newFormData, undefined, this.getFieldId());
});
};

getFieldId() {
Expand Down
2 changes: 1 addition & 1 deletion packages/utils/src/mergeDefaultsWithFormData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,5 @@ export default function mergeDefaultsWithFormData<T = any>(
return acc;
}, acc);
}
return formData;
return formData === undefined ? defaults : formData;
}
8 changes: 6 additions & 2 deletions packages/utils/src/schema/getClosestMatchingOption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export function calculateIndexScore<T = any, S extends StrictRJSFSchema = RJSFSc
validator: ValidatorType<T, S, F>,
rootSchema: S,
schema?: S,
formData: any = {}
formData?: any
): number {
let totalScore = 0;
if (schema) {
Expand Down Expand Up @@ -83,7 +83,11 @@ export function calculateIndexScore<T = any, S extends StrictRJSFSchema = RJSFSc
);
}
if (value.type === 'object') {
return score + calculateIndexScore<T, S, F>(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<T, S, F>(validator, rootSchema, value as S, formValue);
}
if (value.type === guessType(formValue)) {
// If the types match, then we bump the score by one
Expand Down
8 changes: 8 additions & 0 deletions packages/utils/test/mergeDefaultsWithFormData.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion packages/utils/test/schema/getClosestMatchingOptionTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 5db135a

Please sign in to comment.