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
18 changes: 17 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ should change the heading of the (upcoming) version to include a major version b

- Updated most of the widgets to get `formContext` from the `registry` instead of the `props` since it will no longer be passed
- Updated `FieldTemplate`, `ObjectFieldTemplate` and `WrapIfAdditionalTemplate` to rename the old `additionalProperties` interface props to the new ones
- Updated `BaseInputTemplate`, `CheckboxesWidget`, `CheckboxWidget`, `RadioWidget`, `SelectWidget`, and `TextareaWidget` to use `htmlName` for the HTML `name` attribute

## @rjsf/chakra-ui

- Updated `FieldTemplate`, `ObjectFieldTemplate` and `WrapIfAdditionalTemplate` to rename the old `additionalProperties` interface props to the new ones
- Updated `BaseInputTemplate`, `CheckboxesWidget`, `CheckboxWidget`, `RadioWidget`, `SelectWidget`, and `TextareaWidget` to use `htmlName` for the HTML `name` attribute

## @rjsf/core

Expand All @@ -33,48 +35,61 @@ should change the heading of the (upcoming) version to include a major version b
- Updated `ObjectField` to refactor the code from a class component to two stateless functional components, replacing the 3 generator-props with the 4 memoized props mentioned in the `@rjsf/utils` changes
- Updated `Form` to "memoize" the `fieldPathId` and `registry` into the `FormState`, adding a `toIChangeEvent()` helper to restrict the state returned on the `IChangeEvent` interface callbacks
- Updated `FieldTemplate`, `ObjectFieldTemplate` and `WrapIfAdditionalTemplate` to rename the old `additionalProperties` interface props to the new ones
- Added `nameGenerator` prop to `Form` component to enable custom HTML `name` attribute generation for form fields

## @rjsf/daisyui

- Updated the test mocks to remove `formContext` for the widget mock
- Updated `FieldTemplate`, `ObjectFieldTemplate` and `WrapIfAdditionalTemplate` to rename the old `additionalProperties` interface props to the new ones
- Updated `BaseInputTemplate`, `CheckboxesWidget`, `CheckboxWidget`, `RadioWidget`, and `TextareaWidget` to use `htmlName` for the HTML `name` attribute

## @rjsf/fluentui-rc

- Updated `FieldTemplate`, `ObjectFieldTemplate` and `WrapIfAdditionalTemplate` to rename the old `additionalProperties` interface props to the new ones
- Updated `BaseInputTemplate`, `CheckboxesWidget`, `CheckboxWidget`, `RadioWidget`, `SelectWidget`, and `TextareaWidget` to use `htmlName` for the HTML `name` attribute

## @rjsf/mantine

- Updated `FieldTemplate`, `ObjectFieldTemplate` and `WrapIfAdditionalTemplate` to rename the old `additionalProperties` interface props to the new ones
- Updated `BaseInputTemplate`, `CheckboxesWidget`, `CheckboxWidget`, `RadioWidget`, `SelectWidget`, and `TextareaWidget` to use `htmlName` for the HTML `name` attribute

## @rjsf/mui

- Updated `BaseInputTemplate` and `SelectWidget` to remove `formContext` from the props
- Updated `FieldTemplate`, `ObjectFieldTemplate` and `WrapIfAdditionalTemplate` to rename the old `additionalProperties` interface props to the new ones
- Updated `BaseInputTemplate`, `CheckboxesWidget`, `CheckboxWidget`, `RadioWidget`, `SelectWidget`, and `TextareaWidget` to use `htmlName` for the HTML `name` attribute

## @rjsf/primereact

- Updated `SelectWidget` to remove `formContext` from the props
- Updated `FieldTemplate`, `ObjectFieldTemplate` and `WrapIfAdditionalTemplate` to rename the old `additionalProperties` interface props to the new ones
- Updated `BaseInputTemplate`, `CheckboxesWidget`, `CheckboxWidget`, `RadioWidget`, `SelectWidget`, and `TextareaWidget` to use `htmlName` for the HTML `name` attribute

## @rjsf/react-bootstrap

- Updated `FieldTemplate`, `ObjectFieldTemplate` and `WrapIfAdditionalTemplate` to rename the old `additionalProperties` interface props to the new ones
- Updated `BaseInputTemplate`, `CheckboxesWidget`, `CheckboxWidget`, `RadioWidget`, `SelectWidget`, and `TextareaWidget` to use `htmlName` for the HTML `name` attribute

## @rjsf/semantic-ui

- Updated `FieldTemplate`, `ObjectFieldTemplate` and `WrapIfAdditionalTemplate` to rename the old `additionalProperties` interface props to the new ones
- Updated `BaseInputTemplate`, `CheckboxesWidget`, `CheckboxWidget`, `RadioWidget`, `SelectWidget`, and `TextareaWidget` to use `htmlName` for the HTML `name` attribute

## @rjsf/shadcn

- Updated the test mocks to remove `formContext` for the widget mock and added `globalFormOptions` in the registry mock
- Updated `FieldTemplate`, `ObjectFieldTemplate` and `WrapIfAdditionalTemplate` to rename the old `additionalProperties` interface props to the new ones
- Updated `BaseInputTemplate`, `CheckboxesWidget`, `CheckboxWidget`, `SelectWidget`, and `TextareaWidget` to use `htmlName` for the HTML `name` attribute (Note: `RadioWidget` does not support `htmlName` due to Radix UI RadioGroup limitations)

## @rjsf/utils

- BREAKING CHANGE: Updated `FieldTemplateProps` and `WrapIfAdditionalTemplateProps` to replace the `onKeyChange()` and `onDropPropertyClick()` callback generator props with the `onKeyRename()`, `onKeyRenameBlur()` and `onRemoveProperty()` callback props
- BREAKING CHANGE: Updated `ObjectFieldTemplateProps` to replace the `onAddClick()` callback generator prop with the `onAddProperty()` callback prop
- Added new hook `useDeepCompareMemo()` and its associated tests
- Added `NameGeneratorFunction` type and two built-in name generators: `bracketNameGenerator` and `dotNotationNameGenerator`
- Updated `GlobalFormOptions` type to include optional `nameGenerator` field
- Updated `toFieldPathId()` function to support name generation via the `nameGenerator` option in `GlobalFormOptions`
- Added `htmlName` field to `WidgetProps` interface to provide the generated HTML `name` attribute to widgets

## Dev / docs / playground
- Updated the `formTests.tsx` snapshots to add an `anyOf` of all arrays with different item types and removed the disabling of the optional data controls feature for the optional object with oneOfs
Expand All @@ -86,6 +101,7 @@ should change the heading of the (upcoming) version to include a major version b
- Updated the `custom-templates.md` documentation to reflect the `additionalProperties`-based interface props replacement
- Updated the `utility-functions.mf` documenation to add the new `useDeepCompareMemo()` hook
- Updated the `v6.x upgrade guide.md` documentation to add the BREAKING CHANGES to the `FieldTemplateProps`, `ObjectFieldTemplateProps` and `WrapIfAdditionalTemplateProps` interface props changes and the `useDeepCompareMemo()` hook
- Added documentation for the `nameGenerator` prop in `form-props.md` and v6.x upgrade guide

# 6.0.0-beta.21

Expand Down Expand Up @@ -209,7 +225,7 @@ should change the heading of the (upcoming) version to include a major version b
- `ObjectField` and `ArrayField` to use `toFieldPathId` instead of `toIdSchema()` to generate the `fieldPathId`s of all its children
- Updated the `onChange` handling of fields to make `path` required and either pass it straight through, or use the `fieldPathId.path` instead of using an empty array or appending path information
- Updated `Form` to use `toFieldPathId()` to generate `fieldPathId` instead of `idSchema`, always providing the `idPrefix` and `idSeparator` in the `globalFormOptions` and make the `path: FieldPathList` required
- Updated `LayoutGridField` to remove the `IdSchema` related code in favor of `FieldPathId` code
- Updated `LayoutGridField` to remove the `IdSchema` related code in favor of `FieldPathId` code
- Also exported the `getTestRegistry()` function from the main `index.ts` to assist developers in creating `registry` object for tests
- Updated all of the test to deal with the `idSchema` -> `fieldPathId` changes

Expand Down
5 changes: 3 additions & 2 deletions packages/antd/src/templates/BaseInputTemplate/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export default function BaseInputTemplate<
disabled,
registry,
id,
htmlName,
onBlur,
onChange,
onChangeOverride,
Expand Down Expand Up @@ -60,7 +61,7 @@ export default function BaseInputTemplate<
<InputNumber
disabled={disabled || (readonlyAsDisabled && readonly)}
id={id}
name={id}
name={htmlName || id}
onBlur={!readonly ? handleBlur : undefined}
onChange={!readonly ? handleNumberChange : undefined}
onFocus={!readonly ? handleFocus : undefined}
Expand All @@ -75,7 +76,7 @@ export default function BaseInputTemplate<
<Input
disabled={disabled || (readonlyAsDisabled && readonly)}
id={id}
name={id}
name={htmlName || id}
onBlur={!readonly ? handleBlur : undefined}
onChange={!readonly ? handleTextChange : undefined}
onFocus={!readonly ? handleFocus : undefined}
Expand Down
5 changes: 3 additions & 2 deletions packages/antd/src/widgets/CheckboxWidget/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export default function CheckboxWidget<
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
>(props: WidgetProps<T, S, F>) {
const { autofocus, disabled, registry, id, label, hideLabel, onBlur, onChange, onFocus, readonly, value } = props;
const { autofocus, disabled, registry, id, htmlName, label, hideLabel, onBlur, onChange, onFocus, readonly, value } =
props;
const { formContext } = registry;
const { readonlyAsDisabled = true } = formContext as GenericObjectType;

Expand All @@ -42,7 +43,7 @@ export default function CheckboxWidget<
checked={typeof value === 'undefined' ? false : value}
disabled={disabled || (readonlyAsDisabled && readonly)}
id={id}
name={id}
name={htmlName || id}
onChange={!readonly ? handleChange : undefined}
{...extraProps}
aria-describedby={ariaDescribedByIds(id)}
Expand Down
18 changes: 15 additions & 3 deletions packages/antd/src/widgets/CheckboxesWidget/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,19 @@ export default function CheckboxesWidget<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
>({ autofocus, disabled, registry, id, onBlur, onChange, onFocus, options, readonly, value }: WidgetProps<T, S, F>) {
>({
autofocus,
disabled,
registry,
id,
htmlName,
onBlur,
onChange,
onFocus,
options,
readonly,
value,
}: WidgetProps<T, S, F>) {
const { formContext } = registry;
const { readonlyAsDisabled = true } = formContext as GenericObjectType;

Expand Down Expand Up @@ -49,7 +61,7 @@ export default function CheckboxesWidget<
<>
<Checkbox.Group
disabled={disabled || (readonlyAsDisabled && readonly)}
name={id}
name={htmlName || id}
onChange={!readonly ? handleChange : undefined}
value={selectedIndexes}
{...extraProps}
Expand All @@ -60,7 +72,7 @@ export default function CheckboxesWidget<
<span key={i}>
<Checkbox
id={optionId(id, i)}
name={id}
name={htmlName || id}
autoFocus={i === 0 ? autofocus : false}
disabled={Array.isArray(enumDisabled) && enumDisabled.indexOf(option.value) !== -1}
value={String(i)}
Expand Down
5 changes: 3 additions & 2 deletions packages/antd/src/widgets/RadioWidget/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export default function RadioWidget<T = any, S extends StrictRJSFSchema = RJSFSc
disabled,
registry,
id,
htmlName,
onBlur,
onChange,
onFocus,
Expand Down Expand Up @@ -49,7 +50,7 @@ export default function RadioWidget<T = any, S extends StrictRJSFSchema = RJSFSc
<Radio.Group
disabled={disabled || (readonlyAsDisabled && readonly)}
id={id}
name={id}
name={htmlName || id}
onChange={!readonly ? handleChange : undefined}
onBlur={!readonly ? handleBlur : undefined}
onFocus={!readonly ? handleFocus : undefined}
Expand All @@ -60,7 +61,7 @@ export default function RadioWidget<T = any, S extends StrictRJSFSchema = RJSFSc
enumOptions.map((option, i) => (
<Radio
id={optionId(id, i)}
name={id}
name={htmlName || id}
autoFocus={i === 0 ? autofocus : false}
disabled={disabled || (Array.isArray(enumDisabled) && enumDisabled.indexOf(option.value) !== -1)}
key={i}
Expand Down
3 changes: 2 additions & 1 deletion packages/antd/src/widgets/SelectWidget/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default function SelectWidget<
disabled,
registry,
id,
htmlName,
multiple,
onBlur,
onChange,
Expand Down Expand Up @@ -67,7 +68,7 @@ export default function SelectWidget<
// Antd's typescript definitions do not contain the following props that are actually necessary and, if provided,
// they are used, so hacking them in via by spreading `extraProps` on the component to avoid typescript errors
const extraProps = {
name: id,
name: htmlName || id,
};

const showPlaceholderOption = !multiple && schema.default === undefined;
Expand Down
16 changes: 14 additions & 2 deletions packages/antd/src/widgets/TextareaWidget/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,19 @@ export default function TextareaWidget<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
>({ disabled, registry, id, onBlur, onChange, onFocus, options, placeholder, readonly, value }: WidgetProps<T, S, F>) {
>({
disabled,
registry,
id,
htmlName,
onBlur,
onChange,
onFocus,
options,
placeholder,
readonly,
value,
}: WidgetProps<T, S, F>) {
const { formContext } = registry;
const { readonlyAsDisabled = true } = formContext as GenericObjectType;

Expand All @@ -42,7 +54,7 @@ export default function TextareaWidget<
<Input.TextArea
disabled={disabled || (readonlyAsDisabled && readonly)}
id={id}
name={id}
name={htmlName || id}
onBlur={!readonly ? handleBlur : undefined}
onChange={!readonly ? handleChange : undefined}
onFocus={!readonly ? handleFocus : undefined}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default function BaseInputTemplate<
>(props: BaseInputTemplateProps<T, S, F>) {
const {
id,
htmlName,
type,
value,
label,
Expand Down Expand Up @@ -60,7 +61,7 @@ export default function BaseInputTemplate<
>
<Input
id={id}
name={id}
name={htmlName || id}
value={value || value === 0 ? value : ''}
onChange={onChangeOverride || _onChange}
onBlur={_onBlur}
Expand Down
3 changes: 2 additions & 1 deletion packages/chakra-ui/src/CheckboxWidget/CheckboxWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default function CheckboxWidget<
>(props: WidgetProps<T, S, F>) {
const {
id,
htmlName,
value,
disabled,
readonly,
Expand Down Expand Up @@ -66,7 +67,7 @@ export default function CheckboxWidget<
)}
<Checkbox
id={id}
name={id}
name={htmlName || id}
checked={typeof value === 'undefined' ? false : value}
disabled={disabled || readonly}
onCheckedChange={_onChange}
Expand Down
3 changes: 2 additions & 1 deletion packages/chakra-ui/src/CheckboxesWidget/CheckboxesWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export default function CheckboxesWidget<
>(props: WidgetProps<T, S, F>) {
const {
id,
htmlName,
disabled,
options,
value,
Expand Down Expand Up @@ -70,7 +71,7 @@ export default function CheckboxesWidget<
<Checkbox
key={index}
id={optionId(id, index)}
name={id}
name={htmlName || id}
value={String(index)}
disabled={disabled || itemDisabled || readonly}
onBlur={_onBlur}
Expand Down
3 changes: 2 additions & 1 deletion packages/chakra-ui/src/RadioWidget/RadioWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { getChakra } from '../utils';

export default function RadioWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>({
id,
htmlName,
options,
value,
required,
Expand Down Expand Up @@ -58,7 +59,7 @@ export default function RadioWidget<T = any, S extends StrictRJSFSchema = RJSFSc
onBlur={_onBlur}
onFocus={_onFocus}
value={selectedIndex}
name={id}
name={htmlName || id}
aria-describedby={ariaDescribedByIds(id)}
>
<Stack direction={row ? 'row' : 'column'}>
Expand Down
3 changes: 2 additions & 1 deletion packages/chakra-ui/src/SelectWidget/SelectWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default function SelectWidget<T = any, S extends StrictRJSFSchema = RJSFS
) {
const {
id,
htmlName,
options,
label,
hideLabel,
Expand Down Expand Up @@ -126,7 +127,7 @@ export default function SelectWidget<T = any, S extends StrictRJSFSchema = RJSFS
<SelectRoot
collection={selectOptions}
id={id}
name={id}
name={htmlName || id}
multiple={isMultiple}
closeOnSelect={!isMultiple}
onBlur={_onBlur}
Expand Down
3 changes: 2 additions & 1 deletion packages/chakra-ui/src/TextareaWidget/TextareaWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default function TextareaWidget<
F extends FormContextType = any,
>({
id,
htmlName,
placeholder,
value,
label,
Expand Down Expand Up @@ -52,7 +53,7 @@ export default function TextareaWidget<
>
<Textarea
id={id}
name={id}
name={htmlName || id}
value={value ?? ''}
placeholder={placeholder}
autoFocus={autofocus}
Expand Down
12 changes: 11 additions & 1 deletion packages/core/src/components/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
GlobalFormOptions,
ERRORS_KEY,
ID_KEY,
NameGeneratorFunction,
} from '@rjsf/utils';
import _cloneDeep from 'lodash/cloneDeep';
import _get from 'lodash/get';
Expand Down Expand Up @@ -196,6 +197,9 @@ export interface FormProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
* to put the second parameter before the first in its translation.
*/
translateString?: Registry['translateString'];
/** Optional function to generate custom HTML `name` attributes for form fields.
*/
nameGenerator?: NameGeneratorFunction;
/** Optional configuration object with flags, if provided, allows users to override default form state behavior
* Currently only affecting minItems on array fields and handling of setting defaults based on the value of
* `emptyObjectFields`
Expand Down Expand Up @@ -1017,10 +1021,16 @@ export default class Form<
experimental_componentUpdateStrategy,
idSeparator = DEFAULT_ID_SEPARATOR,
idPrefix = DEFAULT_ID_PREFIX,
nameGenerator,
} = props;
const rootFieldId = uiSchema['ui:rootFieldId'];
// Omit any options that are undefined or null
return { idPrefix: rootFieldId || idPrefix, idSeparator, experimental_componentUpdateStrategy };
return {
idPrefix: rootFieldId || idPrefix,
idSeparator,
...(experimental_componentUpdateStrategy !== undefined && { experimental_componentUpdateStrategy }),
...(nameGenerator !== undefined && { nameGenerator }),
};
}

/** Computed the registry for the form using the given `props`, `schema` and `schemaUtils` */
Expand Down
Loading