Reputation: 73
I am trying to implement deselect option in material UI select component.My question is 'is there any prop that automatically deselect the selected object after clicking the selected Object?'
my code snippet:
<FormControl>
<InputLabel>{t('typeUsers')}</InputLabel>
<Select
label={t('typeUsers')}
value={filterUser}
onChange={(e) => { setFilterUser(e.target.value); }}
>
{Object.values(users).filter((user) => (user.administrator === false)).map((user) => (<MenuItem key={user.id} value={user.id}>{user.name}</MenuItem>))}
</Select>
</FormControl>
OR how can I add an additional MenuItem that sets selected Item deslected?
Upvotes: 2
Views: 5867
Reputation: 1
Like others have already suggested to use onClick
handler on menu item, I have resolved this issue by using the dataset
property of the target object, as below:
<MenuItem
key={someValue}
value={someValue}
onClick={(event) => {
if (
event.target.dataset.value === someValue
) {
// reset someValue, eg,
setSomeValue('');
}
}}
>
{someValue}
</MenuItem>
Upvotes: 0
Reputation: 41
I've ran to the same issue recently, and I have found the solution is rather easy. my solution is to add an additional MenuItem inside the select and simply include a "None" or "Clear" option and give it an empty string in the value. it looks like this using your code:-
<FormControl>
<InputLabel>{t('typeUsers')}</InputLabel>
<Select
label={t('typeUsers')}
value={filterUser}
onChange={(e) => { setFilterUser(e.target.value); }}
>
{/* Option for clearing the selection */}
<MenuItem value="">
<em>None</em>
</MenuItem>
{/* Other user options */}
{Object.values(users).filter((user) => (user.administrator === false)).map((user) => (
<MenuItem key={user.id} value={user.id}>
{user.name}
</MenuItem>
))}
</Select>
</FormControl>
When this option is selected, the value will be an empty string i.e nothing selected! Hope it helps.
Upvotes: 1
Reputation: 21
You can use conditional rendering on your "Clear selection" MenuItem with an empty value.
{filterUser && (<MenuItem value=""><em>Clear selection</em></MenuItem>)}
This way, "clear selection" will be shown only if you have selected any option. Here's your fixed code:
<FormControl>
<InputLabel>{t("typeUsers")}</InputLabel>
<Select
label={t("typeUsers")}
value={filterUser}
onChange={(e) => {
setFilterUser(e.target.value);
}}>
{filterUser && (
<MenuItem value="">
<em>Clear selection</em>
</MenuItem>
)}
{Object.values(users)
.filter((user) => user.administrator === false)
.map((user) => (
<MenuItem key={user.id} value={user.id}>
{user.name}
</MenuItem>
))}
</Select>
</FormControl>
Upvotes: 0
Reputation: 799
It's a bit of an hack, but it worked for me: I assigned an additional onClick handler to the MenuItem element, then listened for clickEvent.target.selected === true
to check if the same item has been clicked while active.
If using typescript the handler could be something like this:
onClick={ (clickEvent) => {
if ((clickEvent.target as HTMLOptionElement).selected === true) {
// do my stateful reset
}
} }
Upvotes: 1
Reputation: 655
Unfortunately, the onChange event doesn't fire if the user selects an item that's currently selected, as you found. I got around this by adding an onClick handler to the menu item and comparing its value to the current selection value, then setting the selection to undefined if they match.
Upvotes: 0
Reputation: 4518
Add the following menu item above where you iterate through users
<MenuItem key='clear' value='clear'>Clear selection</MenuItem>
And here is the onChange
for the Select
component
onChange={e => setFilterUser(e.target.value === 'clear' ? '' : e.target.value)}
<FormControl>
<InputLabel>{t('typeUsers')}</InputLabel>
<Select
label={t('typeUsers')}
value={filterUser}
onChange={e => setFilterUser(e.target.value === 'clear' ? '' : e.target.value)}
>
<MenuItem key='clear' value='clear'>Clear selection</MenuItem>
{Object.values(users).filter((user) => (user.administrator === false)).map((user) => (<MenuItem key={user.id} value={user.id}>{user.name}</MenuItem>))}
</Select>
</FormControl>
Upvotes: 1