Skip to content

Commit

Permalink
AB#994 Add option to render enums as select dropdown
Browse files Browse the repository at this point in the history
An enum will be a single select, an enumset will be a multiselect.
The number of visible entries in the select can be set with the htmlSize property.
  • Loading branch information
gjvoosten committed Dec 21, 2023
1 parent bc1c51a commit d8d6a23
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 13 deletions.
8 changes: 8 additions & 0 deletions anet-dictionary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -643,13 +643,21 @@ fields:
type: enumset
label: Choose one or more of the options
helpText: Help text for choosing multiple values
asA: select
htmlSize: 4
choices:
opt1:
label: Option 1
opt2:
label: Option 2
opt3:
label: Option 3
opt4:
label: Option 4
opt5:
label: Option 5
opt6:
label: Option 6
inputFieldName:
type: text
label: Text field
Expand Down
132 changes: 119 additions & 13 deletions client/src/components/FieldHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
Form,
FormControl,
FormGroup,
FormSelect,
InputGroup,
ListGroup,
Row,
Expand Down Expand Up @@ -520,30 +521,135 @@ ButtonToggleGroupField.propTypes = {
export const RadioButtonToggleGroupField = ({
field, // { name, value, onChange, onBlur }
form, // also values, setXXXX, handleXXXX, dirty, isValid, status, etc.
asA,
enableClear,
...props
}) => (
<ButtonToggleGroupField field={field} form={form} type="radio" {...props} />
)
}) =>
(asA === "select" && (
<SelectField field={field} form={form} {...props} />
)) || (
<ButtonToggleGroupField
field={field}
form={form}
type="radio"
enableClear={enableClear}
{...props}
/>
)
RadioButtonToggleGroupField.propTypes = {
field: PropTypes.object,
form: PropTypes.object
form: PropTypes.object,
asA: PropTypes.string,
enableClear: PropTypes.bool
}

export const CheckboxButtonToggleGroupField = ({
field, // { name, value, onChange, onBlur }
form, // also values, setXXXX, handleXXXX, dirty, isValid, status, etc.
asA,
enableClear,
...props
}) => (
<ButtonToggleGroupField
field={field}
form={form}
type="checkbox"
{...props}
/>
)
}) =>
(asA === "select" && (
<SelectField field={field} form={form} multiple {...props} />
)) || (
<ButtonToggleGroupField
field={field}
form={form}
type="checkbox"
enableClear={enableClear}
{...props}
/>
)
CheckboxButtonToggleGroupField.propTypes = {
field: PropTypes.object,
form: PropTypes.object
form: PropTypes.object,
asA: PropTypes.string,
enableClear: PropTypes.bool
}

export const SelectField = ({
field, // { name, value, onChange, onBlur }
form, // contains, touched, errors, values, setXXXX, handleXXXX, dirty, isValid, status, etc.
label,
buttons,
multiple,
onChange,
className,
children,
extraColElem,
addon,
vertical,
extraAddon,
...otherProps
}) => {
const { validationState } = getFormGroupValidationState(field, form)
if (validationState) {
className = classNames(className, "is-invalid")
}
const widgetElem = useMemo(
() => (
<FormSelect
{...field}
value={field.value ?? ""}
multiple={multiple}
isInvalid={validationState}
className={className}
onChange={e => {
let newValue
if (!multiple) {
// First (empty) option must be the empty string (""); replace with null when selected
newValue = e.target.value || null
} else {
newValue = []
for (const opt of e.target.options) {
if (opt.selected) {
newValue.push(opt.value)
}
}
}
onChange(newValue)
}}
{...otherProps}
>
{!multiple && <option />}
{buttons.map(option => (
<option key={`${field.name}_${option.value}`} value={option.value}>
{option.label}
</option>
))}
</FormSelect>
),
[field, className, otherProps, buttons, multiple, onChange, validationState]
)
return (
<Field
field={field}
form={form}
label={label}
widgetElem={widgetElem}
extraColElem={extraColElem}
addon={addon}
vertical={vertical}
extraAddon={extraAddon}
>
{children}
</Field>
)
}
SelectField.propTypes = {
field: PropTypes.object,
form: PropTypes.object,
label: PropTypes.string,
buttons: PropTypes.array.isRequired,
multiple: PropTypes.bool,
onChange: PropTypes.func.isRequired,
className: PropTypes.string,
children: PropTypes.any,
extraColElem: PropTypes.object,
addon: PropTypes.object,
vertical: PropTypes.bool,
extraAddon: PropTypes.object
}

export default Field
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/anet-schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ $defs:
type: string
asA:
type: string
htmlSize:
type: number
filters:
type: array
uniqueItems: true
Expand Down

0 comments on commit d8d6a23

Please sign in to comment.