Is there a way to directly hook up the Polaris Combobox to @shopify/react-form?
Following the default example for the Combobox
where the available options are filtered as you type, it requires hooking into onChange
which is under the control of useForm
when hooked up directly.
Perhaps there's some good examples of this scenario out there in the wild that I've not managed to find yet?
The solution I came up with was to take the default example for the Combobox
, wrap it in a component, then pass in the field properties from useForm
.
<SearchableCombobox
options={data.timezones.map((timezone) => timezone.label)}
label="Time zone"
helpText="The time zone used by CargoWise for saving dates."
value={fields.timezone.value}
onChange={fields.timezone.onChange}
onBlur={fields.timezone.onBlur}
error={fields.timezone.error}
/>
Then in the component, modifying the original example code to use the useForm
properties and passing along the onChange
event:
<Combobox.TextField
prefix={<Icon source={SearchIcon} />}
label={props.label}
labelHidden={typeof props.label === 'undefined'}
helpText={props.helpText}
value={inputValue}
placeholder={props.placeholder}
autoComplete="off"
onBlur={props.onBlur}
onChange={updateText}
error={props.error}
/>
const updateText = useCallback(
(value: string) => {
setInputValue(value);
if (value === '') {
setOptions(deselectedOptions);
if (props.onChange) {
// Pass the underlying value along
props.onChange(value);
}
return;
}
const filterRegex = new RegExp(escapeSpecialRegExCharacters(value), 'i');
const resultOptions = deselectedOptions.filter((option) =>
option.match(filterRegex),
);
setOptions(resultOptions);
},
[deselectedOptions, escapeSpecialRegExCharacters],
);
const updateSelection = useCallback(
(selected: string) => {
const filterRegex = new RegExp(escapeSpecialRegExCharacters(selected), 'i');
const matchedOption = options.find((option) => {
return option.match(filterRegex);
});
setSelectedOption(selected);
setInputValue(matchedOption || '');
if (props.onChange) {
// Pass the underlying value along
props.onChange(matchedOption);
}
},
[options],
);