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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,15 @@ should change the heading of the (upcoming) version to include a major version b
- Added `getChakra` to package exports
- Restored the `ui:options` customization

## @rjsf/core

- Updated `LayoutGridField` to use the pre-existing `UI_GLOBAL_OPTIONS_KEY` instead of its own, incorrect one.

## @rjsf/util

- Fixed form data propagation with `patternProperties` [#4617](https://github.com/rjsf-team/react-jsonschema-form/pull/4617)
- Fixed issue where oneOf schema references could not be modified when defaults were set, fixing [#4580](https://github.com/rjsf-team/react-jsonschema-form/issues/4580).
- Updated the `GlobalUISchemaOptions` types to extend `GenericObjectType` to support user-defined values for their extensions

## Dev / docs / playground

Expand Down
9 changes: 3 additions & 6 deletions packages/core/src/components/fields/LayoutGridField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
SchemaUtilsType,
StrictRJSFSchema,
UI_OPTIONS_KEY,
UI_GLOBAL_OPTIONS_KEY,
UiSchema,
} from '@rjsf/utils';
import cloneDeep from 'lodash/cloneDeep';
Expand Down Expand Up @@ -101,10 +102,6 @@ export const LAYOUT_GRID_UI_OPTION = 'layoutGrid';
*/
export const LAYOUT_GRID_OPTION = `ui:${LAYOUT_GRID_UI_OPTION}`;

/** The constant representing the global UI Options object potentially contained within the `uiSchema`
*/
export const UI_GLOBAL_OPTIONS = 'ui:global_options';

/** Type used to return options list and whether it has a discriminator */
type OneOfOptionsInfoType<S extends StrictRJSFSchema = RJSFSchema> = { options: S[]; hasDiscriminator: boolean };

Expand Down Expand Up @@ -386,7 +383,7 @@ export default class LayoutGridField<
schemaReadonly?: boolean,
forceReadonly?: boolean,
) {
const globalUiOptions = get(uiSchema, [UI_GLOBAL_OPTIONS], {});
const globalUiOptions = get(uiSchema, [UI_GLOBAL_OPTIONS_KEY], {});
const localUiSchema = get(uiSchema, field);
const localUiOptions = { ...get(localUiSchema, [UI_OPTIONS_KEY], {}), ...uiProps, ...globalUiOptions };
const fieldUiSchema = { ...localUiSchema };
Expand All @@ -395,7 +392,7 @@ export default class LayoutGridField<
}
if (!isEmpty(globalUiOptions)) {
// pass the global uiOptions down to the field uiSchema so that they can be applied to all nested fields
set(fieldUiSchema, [UI_GLOBAL_OPTIONS], globalUiOptions);
set(fieldUiSchema, [UI_GLOBAL_OPTIONS_KEY], globalUiOptions);
}
let { readonly: uiReadonly } = getUiOptions<T, S, F>(fieldUiSchema);
if (forceReadonly === true || (isUndefined(uiReadonly) && schemaReadonly === true)) {
Expand Down
16 changes: 8 additions & 8 deletions packages/core/test/LayoutGridField.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
sortedJSONStringify,
toIdSchema,
UI_OPTIONS_KEY,
UI_GLOBAL_OPTIONS_KEY,
UiSchema,
} from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';
Expand All @@ -29,7 +30,6 @@ import LayoutGridField, {
LAYOUT_GRID_OPTION,
LayoutGridFieldProps,
Operators,
UI_GLOBAL_OPTIONS,
} from '../src/components/fields/LayoutGridField';
import { SAMPLE_SCHEMA, sampleUISchema, SIMPLE_ONEOF, SIMPLE_ONEOF_OPTIONS } from './testData/layoutData';
import getTestRegistry from './testData/getTestRegistry';
Expand Down Expand Up @@ -590,7 +590,7 @@ function FakeSchemaField({ 'data-testid': testId, ...props }: Readonly<FieldProp
const { idSchema, formData, onChange, onBlur, onFocus, uiSchema } = props;
const { [ID_KEY]: id } = idSchema;
// Special test case that will pass an error schema into on change to allow coverage
const error = has(uiSchema, UI_GLOBAL_OPTIONS) ? EXTRA_ERROR : undefined;
const error = has(uiSchema, UI_GLOBAL_OPTIONS_KEY) ? EXTRA_ERROR : undefined;
const onTextChange = ({ target: { value: val } }: ChangeEvent<HTMLInputElement>) => {
onChange(val, error, id);
};
Expand Down Expand Up @@ -693,7 +693,7 @@ function getExpectedPropsForField(
const idSchema = get(props.idSchema, field)!;
const formData = get(props.formData, field);
// Also extract any global props
const global = get(props.uiSchema, [UI_GLOBAL_OPTIONS]);
const global = get(props.uiSchema, [UI_GLOBAL_OPTIONS_KEY]);
const fieldUISchema = get(props.uiSchema, field);
const { readonly: uiReadonly } = getUiOptions(fieldUISchema);
// The expected props are the FORWARDED_PROPS, the field name, sub-schema, sub-uiSchema and sub-idSchema
Expand All @@ -709,7 +709,7 @@ function getExpectedPropsForField(
uiSchema: {
...uiSchema,
[UI_OPTIONS_KEY]: { ...global, ...otherUiProps }, // spread the global and other ui keys into the ui:options
...(global ? { [UI_GLOBAL_OPTIONS]: global } : {}), // ensure the globals are maintained
...(global ? { [UI_GLOBAL_OPTIONS_KEY]: global } : {}), // ensure the globals are maintained
},
idSchema,
errorSchema,
Expand Down Expand Up @@ -1208,12 +1208,12 @@ describe('LayoutGridField', () => {
test('field with uiProps and uiSchema with global options for the field', () => {
const uiProps = { fullWidth: true };
const globalOptions = { label: false };
const uiSchema = { foo: { 'ui:widget': 'bar' }, [UI_GLOBAL_OPTIONS]: globalOptions };
const uiSchema = { foo: { 'ui:widget': 'bar' }, [UI_GLOBAL_OPTIONS_KEY]: globalOptions };
expect(LayoutGridField.computeFieldUiSchema('foo', uiProps, uiSchema)).toEqual({
fieldUiSchema: {
...uiSchema.foo,
[UI_OPTIONS_KEY]: { ...uiProps, ...globalOptions },
[UI_GLOBAL_OPTIONS]: globalOptions,
[UI_GLOBAL_OPTIONS_KEY]: globalOptions,
},
uiReadonly: undefined,
});
Expand Down Expand Up @@ -1386,7 +1386,7 @@ describe('LayoutGridField', () => {
const otherUIProps = { inline: true };
const props = getProps({
schema: GRID_FORM_SCHEMA,
uiSchema: { ...gridFormUISchema, [UI_GLOBAL_OPTIONS]: globalUiOptions },
uiSchema: { ...gridFormUISchema, [UI_GLOBAL_OPTIONS_KEY]: globalUiOptions },
formData: {},
errorSchema: { employment: {} },
// IdSchema is weirdly recursive and it's easier to just ignore the error
Expand Down Expand Up @@ -1513,7 +1513,7 @@ describe('LayoutGridField', () => {
const gridProps = { operator: Operators.NONE, field: fieldName, value: null };
const props = getProps({
schema: SAMPLE_SCHEMA,
uiSchema: { ...sampleUISchema, [UI_GLOBAL_OPTIONS]: { always: 'there' } },
uiSchema: { ...sampleUISchema, [UI_GLOBAL_OPTIONS_KEY]: { always: 'there' } },
formData: { [fieldName]: 'foo' },
layoutGridSchema: { [GridType.CONDITION]: { ...gridProps, children: GRID_CHILDREN } },
registry: sampleSchemaRegistry,
Expand Down
5 changes: 3 additions & 2 deletions packages/utils/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -370,9 +370,10 @@ export type TemplatesType<T = any, S extends StrictRJSFSchema = RJSFSchema, F ex
};

/** The set of UiSchema options that can be set globally and used as fallbacks at an individual template, field or
* widget level when no field-level value of the option is provided.
* widget level when no field-level value of the option is provided. Extends GenericObjectType to support allowing users
* to provide any value they need for their customizations.
*/
export type GlobalUISchemaOptions = {
export type GlobalUISchemaOptions = GenericObjectType & {
/** Flag, if set to `false`, new items cannot be added to array fields, unless overridden (defaults to true) */
addable?: boolean;
/** Flag, if set to `true`, array items can be copied (defaults to false) */
Expand Down