I have the following Autocomplete
component:
<Autocomplete
options={channels}
autoHighlight
multiple
disableCloseOnSelect
value={form.channel_ids}
getOptionLabel={option => option.name}
onChange={(event, value) => updateForm({...form, channel_ids: value?.map(channel => channel.id)})}
renderInput={params =>
<TextField
{...params}
label="Channels"
error={!!errors?.channel_ids}
helperText={errors?.channel_ids?.[0]}
/>
}
isOptionEqualToValue={(option, value) => option.id === value}
renderOption={(props, option, {selected}) =>
<li {...props}>
<Checkbox
icon={<Icon path={mdiCheckboxBlankOutline} size={1} />}
checkedIcon={<Icon path={mdiCheckboxMarked} size={1} />}
style={{marginRight: 8}}
checked={selected}
/>
{option.name}
</li>
}
/>
The channels array:
[
{id: 1, name: 'Example 1'},
{id: 2, name: 'Example 2'}
]
So far this is working fine:
What isn't working is that it doesn't match the value
and options
. I want the Autocomplete to use an array of objects as options but to return a one dimensional array of selected ids. For example [1]
, [2]
or [1, 2]
.
I hope someone can help me with this. Thanks in advance.
Long story short it's not possible to do it straight away. I read the component's documentation and it is not possible. What I can suggest to you, however, is to keep an external map to do the mapping ID-component in a work-around fashion.
const options = new Map(channels.map((channel) => ([channel.id, channel])))
// Since the option is mapped from the id the empty string will never be picked
const getOptionName = (option: string) => options.get(option)?.name ?? ''
<Autocomplete
options={Array.from(options.keys())} // Modified
autoHighlight
multiple
disableCloseOnSelect
value={form.channel_ids}
getOptionLabel={getOptionName} // Modified
onChange={(event, value) => updateForm({...form, channel_ids: value})} // Modified
renderInput={params =>
<TextField
{...params}
label="Channels"
error={!!errors?.channel_ids}
helperText={errors?.channel_ids?.[0]}
/>
}
isOptionEqualToValue={(option, value) => option === value}
renderOption={(props, option, {selected}) =>
<li {...props}>
<Checkbox
icon={<Icon path={mdiCheckboxBlankOutline} size={1} />}
checkedIcon={<Icon path={mdiCheckboxMarked} size={1} />}
style={{marginRight: 8}}
checked={selected}
/>
{getOptionName(option)} // Modified
</li>
}
/>
Notice: if you think the computation of the map is too expensive in terms of time you can always use a memo.
const options = useMemo(() => new Map(channels.map((channel) => ([channel.id, channel]))),[channels])