Skip to content

Commit

Permalink
🎨 [#4524] Tweak implementation details
Browse files Browse the repository at this point in the history
Attempted to make the code a bit easier/simpler, and clean up the
test helpers to use accessible queries.
  • Loading branch information
sergei-maertens committed Oct 11, 2024
1 parent b3530cb commit 489f3c1
Showing 1 changed file with 43 additions and 36 deletions.
79 changes: 43 additions & 36 deletions src/openforms/js/components/admin/forms/ReactSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,38 @@ const styles = {
}),
};

/**
* Find the option by `value` in the list of possible options.
*
* `options` are the options passed to ReactSelect, which may be a list of options or
* a list of option groups: `(Option | Group)[]`. If an item is a group, it has a nested
* property `options` of type `Option[]`.
*
* See https://github.com/JedWatson/react-select/blob/a8b8f4342cc113e921bb238de2dd69a2d345b5f8/packages/react-select/src/Select.tsx#L406
* for a reference.
*/
const getValue = (options, value) => {
if (!value) {
// 0 could be an actual selected value (!)
if (value == null || value === '') {
return null;
}

// We support grouped ReactSelect options.
// So we need to look in the first, and possible second level of options
for (let index = 0; index < options.length; index++) {
const option = options[index];
if ('value' in option && option.value === value) {
return option;
}
const foundOption = (option?.options || []).find(opt => opt.value === value);
if (foundOption) {
return foundOption;
// check all the options until we find a match on the `value` property for the option.
// ReactSelect allows using different properties for the value, but let's handle that
// when we actually need it.
for (const groupOrOption of options) {
if ('options' in groupOrOption) {
const hit = getValue(groupOrOption.options, value);
if (hit) return hit; // otherwise continue with the rest
} else {
// we're dealing with a plain option, compare the value property
if (groupOrOption.value === value) {
return groupOrOption;
}
}
}

return null;
};

/**
Expand All @@ -59,27 +74,22 @@ const getValue = (options, value) => {
* @deprecated - if possible, refactor the form to use Formik and use the Formik-enabled
* variant.
*/
const SelectWithoutFormik = ({name, options, value, className, onChange, ...props}) => {
const classes = classNames('admin-react-select', {
[`${className}`]: className,
});
return (
<ReactSelect
inputId={`id_${name}`}
name={name}
className={classes}
classNamePrefix="admin-react-select"
styles={styles}
menuPlacement="auto"
options={options}
value={getValue(options, value)}
onChange={selectedOption => {
onChange(selectedOption === null ? undefined : selectedOption.value);
}}
{...props}
/>
);
};
const SelectWithoutFormik = ({name, options, value, className, onChange, ...props}) => (
<ReactSelect
inputId={`id_${name}`}
name={name}
className={classNames('admin-react-select', className)}
classNamePrefix="admin-react-select"
styles={styles}
menuPlacement="auto"
options={options}
value={getValue(options, value)}
onChange={selectedOption => {
onChange(selectedOption === null ? undefined : selectedOption.value);
}}
{...props}
/>
);

/**
* A select dropdown backed by react-select for Formik forms.
Expand All @@ -90,13 +100,10 @@ const SelectWithFormik = ({name, options, className, ...props}) => {
const [fieldProps, , fieldHelpers] = useField(name);
const {value} = fieldProps;
const {setValue} = fieldHelpers;
const classes = classNames('admin-react-select', {
[`${className}`]: className,
});
return (
<ReactSelect
inputId={`id_${name}`}
className={classes}
className={classNames('admin-react-select', className)}
classNamePrefix="admin-react-select"
styles={styles}
menuPlacement="auto"
Expand Down

0 comments on commit 489f3c1

Please sign in to comment.