diff --git a/CHANGELOG.md b/CHANGELOG.md index 0265353174..cfc56f36d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,16 @@ should change the heading of the (upcoming) version to include a major version b --> +# 5.23.0 + +## @rjsf/core + +- Updated `SelectWidget` to support `` through `ui:options` `optgroup`. Fixes [#1813] + +## Dev / docs / playground + +- Updated `samples/widgets` to show `optgroup` usage (`selectWidgetOptions3`) + # 5.22.4 ## @rjsf/utils diff --git a/packages/core/src/components/widgets/SelectWidget.tsx b/packages/core/src/components/widgets/SelectWidget.tsx index 1bebfa371a..bfaf505d10 100644 --- a/packages/core/src/components/widgets/SelectWidget.tsx +++ b/packages/core/src/components/widgets/SelectWidget.tsx @@ -39,7 +39,7 @@ function SelectWidget) { - const { enumOptions, enumDisabled, emptyValue: optEmptyVal } = options; + const { enumOptions, enumDisabled, emptyValue: optEmptyVal, optgroups } = options; const emptyValue = multiple ? [] : ''; const handleFocus = useCallback( @@ -67,7 +67,37 @@ function SelectWidget(value, enumOptions, multiple); - const showPlaceholderOption = !multiple && schema.default === undefined; + + let opts = null + if (optgroups) { + let enumOptionFromValue = new Map() + enumOptions.forEach((enumOption, i) => { + enumOptionFromValue.set(enumOption.value, [enumOption, i]) + }) + opts = Object.keys(optgroups).map(optgroup => { + return ( + {optgroups[optgroup].map(value => { + if (!enumOptionFromValue.has(value)) return null + const disabled = enumDisabled && enumDisabled.indexOf(value) !== -1; + let [{ label }, i] = enumOptionFromValue.get(value) + return ( + + ); + })} + ) + }) + } else { + opts = Array.isArray(enumOptions) && enumOptions.map(({ value, label }, i) => { + const disabled = enumDisabled && enumDisabled.indexOf(value) !== -1; + return ( + + ); + }); + } return ( ); } diff --git a/packages/docs/docs/api-reference/uiSchema.md b/packages/docs/docs/api-reference/uiSchema.md index d4eaaaa208..bd24a637f3 100644 --- a/packages/docs/docs/api-reference/uiSchema.md +++ b/packages/docs/docs/api-reference/uiSchema.md @@ -344,6 +344,32 @@ render(
, docum This property allows you to reorder the properties that are shown for a particular object. See [Objects](../json-schema/objects.md) for more information. +### optgroup + +To leverage `` inside a select to group ``, you can specify how to organize the options using the `optgroups` key inside your uiSchema. + +```tsx +import { Form } from '@rjsf/core'; +import { RJSFSchema, UiSchema } from '@rjsf/utils'; +import validator from '@rjsf/validator-ajv8'; + +const schema: RJSFSchema = { + type: 'string', + enum: ['lorem', 'ipsum', 'dolorem', 'alpha', 'beta', 'gamma'] +}; + +const uiSchema: UiSchema = { + 'ui:options': { + optgroups: { + lipsum: ['lorem', 'ipsum', 'dolorem'], + greek: ['alpha', 'beta', 'gamma'] + } + }, +}; + +render(, document.getElementById('app')); +``` + ### placeholder You can add placeholder text to an input by using the `ui:placeholder` uiSchema directive: diff --git a/packages/playground/src/samples/widgets.tsx b/packages/playground/src/samples/widgets.tsx index a93b2362a5..9049267e92 100644 --- a/packages/playground/src/samples/widgets.tsx +++ b/packages/playground/src/samples/widgets.tsx @@ -106,6 +106,11 @@ const widgets: Sample = { }, ], }, + selectWidgetOptions3: { + title: 'Custom select widget with options grouped by optgroups', + type: 'string', + enum: ['foo', 'bar'], + }, }, }, uiSchema: { @@ -196,6 +201,14 @@ const widgets: Sample = { backgroundColor: 'pink', }, }, + selectWidgetOptions3: { + 'ui:options': { + 'optgroups': { + 'lipsum': ['foo'], + 'dolorem': ['bar'] + } + } + } }, formData: { stringFormats: {