Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Improve support for remix by adding name on all input elements #3145

Merged
merged 6 commits into from
Sep 25, 2022
22 changes: 21 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,48 @@ should change the heading of the (upcoming) version to include a major version b

## @rjsf/antd
- Convert `WrapIfAdditional` to `WrapIfAdditionalTemplate`
- Added `name` to the `input` components that were missing it to support `remix`
- Fixed `CheckboxesWidget` and `RadioWidget` to have unique `id`s for each radio element by appending the `option.value`, protecting against non-arrays

## @rjsf/bootstrap
- Convert `WrapIfAdditional` to `WrapIfAdditionalTemplate`
- Added `name` to the `input` components that were missing it to support `remix`
- Simplified the `CheckboxWidgets` code to eliminate a ternary in favor of a simple `inline={inline}` property since all the rest of the props were the same
- Fixed `CheckboxesWidget` and `RadioWidget` to have unique `id`s for each radio element by appending the `option.value`, removing unnecessary casts to `any` and protecting against non-arrays
- Fixed an issue where `CheckboxesWidget` incorrectly rendered inner `<form>` elements around each checkbox, fixing (https://github.com/rjsf-team/react-jsonschema-form/issues/2355)

## @rjsf/chakra-ui
- Convert `WrapIfAdditional` to `WrapIfAdditionalTemplate`
- Added `name` to the `input` components that were missing it to support `remix`
- Fixed `CheckboxesWidget` and `RadioWidget` to have unique `id`s for each radio element by appending the `option.value`, removing unnecessary casts to `any` and protecting against non-arrays

## @rjsf/core
- Convert `WrapIfAdditional` to `WrapIfAdditionalTemplate`
- Added `name` to the `input` components that were missing it to support `remix`
- Fixed `CheckboxesWidget` and `RadioWidget` to have unique `id`s for each radio element by appending the `option.value`

## @rjsf/fluent-ui
- Add stubbed `WrapIfAdditionalTemplate`. `additionalProperties` is currently not supported in `@rjsf/fluent-ui` (See [#2777](https://github.com/rjsf-team/react-jsonschema-form/issues/2777)).
- Added `name` or `id` (for those fluent components not supporting name) to the `input` components that were missing it to support `remix`
- Fixed `DateTimeWidget` to properly use `BaseInputTemplate` rather than `TextWidget`
- Fixed `CheckboxesWidget` and `RadioWidget` to have unique `id`s for each radio element by appending the `option.value`, removing unnecessary casts and protecting against non-arrays, fixing (https://github.com/rjsf-team/react-jsonschema-form/issues/2138)
- Fixed `RadioWidget` so that it supports read-only and disabled states

## @rjsf/material-ui
- Convert `WrapIfAdditional` to `WrapIfAdditionalTemplate`
- Added `name` to the `input` components that were missing it to support `remix`
- Fixed `CheckboxesWidget` and `RadioWidget` to have unique `id`s for each radio element by appending the `option.value`, removing unnecessary casts to `any` and protecting against non-arrays

## @rjsf/mui
- Convert `WrapIfAdditional` to `WrapIfAdditionalTemplate`
- Added `name` to the `input` components that were missing it to support `remix`
- Fixed `CheckboxesWidget` and `RadioWidget` to have unique `id`s for each radio element by appending the `option.value`, removing unnecessary casts to `any` and protecting against non-arrays

## @rjsf/semantic-ui
- Convert `WrapIfAdditional` to `WrapIfAdditionalTemplate`
- Fixed `ArrayFieldTemplate` and `ObjectFieldTemplate`'s `AddButton` to show the non-labeled version. (https://github.com/rjsf-team/react-jsonschema-form/pull/3142)
- Added `name` to the `input` components that were missing it to support `remix`, including fixing incorrect `name`s as `id`s in some situations
- Fixed `CheckboxesWidget` and `RadioWidget` to have unique `id`s for each radio element by appending the `option.value`, protecting against non-arrays

## @rjsf/utils
- Added `WrapIfAdditionalTemplate` and `WrapIfAdditionalTemplateProps` to simplify theming and make it easier to override Field behavior for schemas with `additionalProperties`.
Expand Down Expand Up @@ -80,7 +101,6 @@ should change the heading of the (upcoming) version to include a major version b
## @rjsf/semantic-ui
- Updated the `FieldErrorTemplate` to use the `children` variation of the `List.Item` that supports ReactElement
- Pass `uiSchema` appropriately to all of the `IconButton`s, `ArrayFieldItemTemplate` and `WrapIfAdditional` components, fixing (https://github.com/rjsf-team/react-jsonschema-form/issues/3130)
- Fixed `ArrayFieldTemplate` and `ObjectFieldTemplate`'s `AddButton` to show the non-labeled version. (https://github.com/rjsf-team/react-jsonschema-form/pull/3142)

## @rjsf/utils
- Updated the `FieldErrorProps` type to make it support an array of string and ReactElement
Expand Down
2 changes: 2 additions & 0 deletions packages/antd/src/widgets/AltDateWidget/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ const AltDateWidget = ({
className="form-control"
disabled={elemProps.disabled}
id={elemProps.id}
name={elemProps.name}
onBlur={elemProps.onBlur}
onChange={(elemValue) => elemProps.select(elemProps.type, elemValue)}
onFocus={elemProps.onFocus}
Expand All @@ -122,6 +123,7 @@ const AltDateWidget = ({
autofocus: autofocus && i === 0,
disabled,
id: elemId,
name: id,
onBlur,
onFocus,
readonly,
Expand Down
30 changes: 18 additions & 12 deletions packages/antd/src/widgets/CheckboxesWidget/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,24 @@ const CheckboxesWidget = ({
onFocus={!readonly ? handleFocus : undefined}
value={value}
>
{enumOptions.map(({ value: optionValue, label: optionLabel }, i) => (
<span key={optionValue}>
<Checkbox
autoFocus={i === 0 ? autofocus : false}
disabled={enumDisabled && enumDisabled.indexOf(value) !== -1}
value={optionValue}
>
{optionLabel}
</Checkbox>
{!inline && <br />}
</span>
))}
{Array.isArray(enumOptions) &&
enumOptions.map(({ value: optionValue, label: optionLabel }, i) => (
<span key={optionValue}>
<Checkbox
id={`${id}-${optionValue}`}
name={id}
autoFocus={i === 0 ? autofocus : false}
disabled={
Array.isArray(enumDisabled) &&
enumDisabled.indexOf(value) !== -1
}
value={optionValue}
>
{optionLabel}
</Checkbox>
{!inline && <br />}
</span>
))}
</Checkbox.Group>
) : null;
};
Expand Down
25 changes: 15 additions & 10 deletions packages/antd/src/widgets/RadioWidget/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,21 @@ const RadioWidget = ({
onFocus={!readonly ? handleFocus : undefined}
value={`${value}`}
>
{enumOptions.map(({ value: optionValue, label: optionLabel }, i) => (
<Radio
autoFocus={i === 0 ? autofocus : false}
disabled={enumDisabled && enumDisabled.indexOf(value) !== -1}
key={`${optionValue}`}
value={`${optionValue}`}
>
{optionLabel}
</Radio>
))}
{Array.isArray(enumOptions) &&
enumOptions.map(({ value: optionValue, label: optionLabel }, i) => (
<Radio
id={`${id}-${optionValue}`}
name={id}
autoFocus={i === 0 ? autofocus : false}
disabled={
Array.isArray(enumDisabled) && enumDisabled.indexOf(value) !== -1
}
key={optionValue}
value={`${optionValue}`}
>
{optionLabel}
</Radio>
))}
</Radio.Group>
);
};
Expand Down
1 change: 1 addition & 0 deletions packages/antd/src/widgets/RangeWidget/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const RangeWidget = ({
autoFocus={autofocus}
disabled={disabled || (readonlyAsDisabled && readonly)}
id={id}
name={id}
max={max}
min={min}
onBlur={!readonly ? handleBlur : undefined}
Expand Down
7 changes: 7 additions & 0 deletions packages/antd/test/__snapshots__/Form.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ exports[`single fields checkboxes field 1`] = `
checked={false}
className="ant-checkbox-input"
disabled={false}
id="root-foo"
name="root"
onBlur={[Function]}
onChange={[Function]}
Expand Down Expand Up @@ -168,6 +169,7 @@ exports[`single fields checkboxes field 1`] = `
checked={false}
className="ant-checkbox-input"
disabled={false}
id="root-bar"
name="root"
onBlur={[Function]}
onChange={[Function]}
Expand Down Expand Up @@ -201,6 +203,7 @@ exports[`single fields checkboxes field 1`] = `
checked={false}
className="ant-checkbox-input"
disabled={false}
id="root-fuzz"
name="root"
onBlur={[Function]}
onChange={[Function]}
Expand Down Expand Up @@ -234,6 +237,7 @@ exports[`single fields checkboxes field 1`] = `
checked={false}
className="ant-checkbox-input"
disabled={false}
id="root-qux"
name="root"
onBlur={[Function]}
onChange={[Function]}
Expand Down Expand Up @@ -1267,6 +1271,7 @@ exports[`single fields radio field 1`] = `
checked={false}
className="ant-radio-input"
disabled={false}
id="root-true"
name="root"
onBlur={[Function]}
onChange={[Function]}
Expand Down Expand Up @@ -1297,6 +1302,7 @@ exports[`single fields radio field 1`] = `
checked={false}
className="ant-radio-input"
disabled={false}
id="root-false"
name="root"
onBlur={[Function]}
onChange={[Function]}
Expand Down Expand Up @@ -1586,6 +1592,7 @@ exports[`single fields string field format data-url 1`] = `
defaultValue=""
disabled={false}
id="root"
name="root"
onChange={[Function]}
type="file"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const BaseInputTemplate = ({
</Form.Label>
<Form.Control
id={id}
name={id}
placeholder={placeholder}
autoFocus={autofocus}
required={required}
Expand Down
1 change: 1 addition & 0 deletions packages/bootstrap-4/src/CheckboxWidget/CheckboxWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const CheckboxWidget = (props: WidgetProps) => {
>
<Form.Check
id={id}
name={id}
label={desc}
checked={typeof value === "undefined" ? false : value}
required={required}
Expand Down
41 changes: 13 additions & 28 deletions packages/bootstrap-4/src/CheckboxesWidget/CheckboxesWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,48 +53,33 @@ const CheckboxesWidget = ({
<>
<Form.Label htmlFor={id}>{label || schema.title}</Form.Label>
<Form.Group>
{(enumOptions as any).map((option: any, index: number) => {
const checked = value.indexOf(option.value) !== -1;
const itemDisabled =
enumDisabled && (enumDisabled as any).indexOf(option.value) != -1;
{Array.isArray(enumOptions) &&
enumOptions.map((option, index: number) => {
const checked = value.indexOf(option.value) !== -1;
const itemDisabled =
Array.isArray(enumDisabled) &&
enumDisabled.indexOf(option.value) !== -1;

return inline ? (
<Form key={index}>
<Form.Check
required={required}
inline
className="bg-transparent border-0"
custom
checked={checked}
type={"checkbox"}
id={`${id}_${index}`}
label={option.label}
autoFocus={autofocus && index === 0}
onChange={_onChange(option)}
onBlur={_onBlur}
onFocus={_onFocus}
disabled={disabled || itemDisabled || readonly}
/>
</Form>
) : (
<Form key={index}>
return (
<Form.Check
key={option.value}
inline={inline}
custom
required={required}
checked={checked}
className="bg-transparent border-0"
type={"checkbox"}
id={`${id}_${index}`}
id={`${id}-${option.value}`}
name={id}
label={option.label}
autoFocus={autofocus && index === 0}
onChange={_onChange(option)}
onBlur={_onBlur}
onFocus={_onFocus}
disabled={disabled || itemDisabled || readonly}
/>
</Form>
);
})}
);
})}
</Form.Group>
</>
);
Expand Down
49 changes: 25 additions & 24 deletions packages/bootstrap-4/src/RadioWidget/RadioWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,31 +39,32 @@ const RadioWidget = ({
{uiOptions.title || schema.title || label}
{(label || uiOptions.title || schema.title) && required ? "*" : null}
</Form.Label>
{(enumOptions as any).map((option: any, i: number) => {
const itemDisabled =
Array.isArray(enumDisabled) &&
enumDisabled.indexOf(option.value) !== -1;
const checked = option.value == value;
{Array.isArray(enumOptions) &&
enumOptions.map((option) => {
const itemDisabled =
Array.isArray(enumDisabled) &&
enumDisabled.indexOf(option.value) !== -1;
const checked = option.value == value;

const radio = (
<Form.Check
inline={inline}
label={option.label}
id={option.label}
key={i}
name={id}
type="radio"
disabled={disabled || itemDisabled || readonly}
checked={checked}
required={required}
value={option.value}
onChange={_onChange}
onBlur={_onBlur}
onFocus={_onFocus}
/>
);
return radio;
})}
const radio = (
<Form.Check
inline={inline}
label={option.label}
id={`${id}-${option.value}`}
key={option.value}
name={id}
type="radio"
disabled={disabled || itemDisabled || readonly}
checked={checked}
required={required}
value={option.value}
onChange={_onChange}
onBlur={_onBlur}
onFocus={_onFocus}
/>
);
return radio;
})}
</Form.Group>
);
};
Expand Down
1 change: 1 addition & 0 deletions packages/bootstrap-4/src/SelectWidget/SelectWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const SelectWidget = ({
as="select"
bsPrefix="custom-select"
id={id}
name={id}
value={typeof value === "undefined" ? emptyValue : value}
required={required}
multiple={multiple}
Expand Down
1 change: 1 addition & 0 deletions packages/bootstrap-4/src/TextareaWidget/TextareaWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const TextareaWidget = ({
<InputGroup>
<FormControl
id={id}
name={id}
as="textarea"
placeholder={placeholder}
disabled={disabled}
Expand Down
7 changes: 5 additions & 2 deletions packages/bootstrap-4/test/CheckboxesWidget.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ describe("CheckboxesWidget", () => {
<CheckboxesWidget
{...makeWidgetMockProps({
options: {
enumOptions: [{ label: "", value: "" }],
enumOptions: [{ label: "A", value: "a" }],
},
})}
/>
Expand All @@ -23,7 +23,10 @@ describe("CheckboxesWidget", () => {
.create(
<CheckboxesWidget
{...makeWidgetMockProps({
options: { enumOptions: [{ label: "", value: "" }], inline: true },
options: {
enumOptions: [{ label: "A", value: "a" }],
inline: true,
},
})}
/>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ exports[`AdditionalProperties tests show add button and fields if additionalProp
className="form-control"
disabled={false}
id="root"
name="root"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
Expand Down
Loading