By default MaterialUI's Select ponent leaves itself focused after selecting an option. This behaviour can be seen in all their examples in their docs
I would like the element to blur once something is selected. Here is what my code currently looks like:
const App = () => {
const [selectedValue, setSelectedValue] = useState('')
const selectElement = useRef(null);
return (
<Select
native
ref={selectElement}
value={selectedValue}
onChange={(evt) => {
setSelectedValue(evt.target.value)
// Attempt at blurring the element upon selection using the useRef:
selectElement.current.blur(); // Nothing happens
// Attempt at blurring the element upon selection using activeElement:
document.activeElement.blur(); // Get Error: "Property 'blur' does not exist on type 'Element'."
}}
>
<option value='option 1'>Option 1</option>
<option value='option 2'>Option 2</option>
<option value='option 3'>Option 3</option>
</Select>
);
};
As you can see in the code, I've tried to do this with two different methods I've found:
Through
useRef()
: this does nothing, no errors or anything, but does not blur my elementThrough the
document.activeElement
: this gives me an error, apparently propertyblur
does not exist on type element.
What is the proper method of blurring my Select ponent upon selecting an option?
By default MaterialUI's Select ponent leaves itself focused after selecting an option. This behaviour can be seen in all their examples in their docs
I would like the element to blur once something is selected. Here is what my code currently looks like:
const App = () => {
const [selectedValue, setSelectedValue] = useState('')
const selectElement = useRef(null);
return (
<Select
native
ref={selectElement}
value={selectedValue}
onChange={(evt) => {
setSelectedValue(evt.target.value)
// Attempt at blurring the element upon selection using the useRef:
selectElement.current.blur(); // Nothing happens
// Attempt at blurring the element upon selection using activeElement:
document.activeElement.blur(); // Get Error: "Property 'blur' does not exist on type 'Element'."
}}
>
<option value='option 1'>Option 1</option>
<option value='option 2'>Option 2</option>
<option value='option 3'>Option 3</option>
</Select>
);
};
As you can see in the code, I've tried to do this with two different methods I've found:
Through
useRef()
: this does nothing, no errors or anything, but does not blur my elementThrough the
document.activeElement
: this gives me an error, apparently propertyblur
does not exist on type element.
What is the proper method of blurring my Select ponent upon selecting an option?
Share Improve this question asked Dec 22, 2020 at 16:03 theJulstheJuls 7,49019 gold badges96 silver badges182 bronze badges 6- You need to defer the blur effect. The focused element is not on the screen after selecting. – Akxe Commented Dec 29, 2020 at 21:22
-
1
Looks like you are trying to blur the option, but I think you want to blur the select itself. Try
selectElement.blur();
orevt.target.blur();
– 2pha Commented Dec 29, 2020 at 22:25 -
Note the ref is being forwarded to the root element (a wrapper div), not the
select
, which is why the that solution does nothing. – ericgio Commented Dec 29, 2020 at 23:20 - The error you're seeing looks TypeScript-related, but you haven't included any typing in your question/code. – ericgio Commented Dec 29, 2020 at 23:42
- I'm curious why you want to blur the Select. This seems like a horrible thing to do from an accessibility standpoint. – Ryan Cogswell Commented Dec 31, 2020 at 17:13
2 Answers
Reset to default 4inspired by @ericgio and @Ryan Cogswell answers there's another way to tackle this. For non-native elements, we can assign a setTimeout
function to the onClose
which will blur the element after selecting the option from menu.
const App = () => {
const [selectedValue, setSelectedValue] = useState('');
const [age, setAge] = React.useState('');
const handleChange = (event) => {
setAge(event.target.value);
};
return (
<div>
<div>
<Select
style={{ width: '200px' }}
native
value={selectedValue}
onChange={(evt) => {
setSelectedValue(evt.target.value);
evt.target.blur();
}}>
<option value="option 1">Option 1</option>
<option value="option 2">Option 2</option>
<option value="option 3">Option 3</option>
</Select>
</div>
<FormControl style={{ width: '200px' }}>
<InputLabel id="demo-simple-select-label">Age</InputLabel>
<Select
onClose={() => {
setTimeout(() => {
document.activeElement.blur();
}, 0);
}}
value={age}
onChange={handleChange}>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</div>
);
};
Sandbox:- https://codesandbox.io/s/wonderful-microservice-xufqc
Summarizing some of the ments into an answer:
As @2pha suggests, using evt.target.blur()
is probably the way to go:
const App = () => {
const [selectedValue, setSelectedValue] = useState('');
return (
<Select
native
value={selectedValue}
onChange={(evt) => {
setSelectedValue(evt.target.value);
console.log(document.activeElement); // <select>
evt.target.blur();
console.log(document.activeElement); // <body>
}}>
<option value="option 1">Option 1</option>
<option value="option 2">Option 2</option>
<option value="option 3">Option 3</option>
</Select>
);
};
Sandbox: https://codesandbox.io/s/empty-night-oqlgr
The ref isn't working because it's being forwarded to the root element (a div
) not the select
element.
The error you're seeing related to document.activeElement
looks TypeScript-related. You're seeing it because document.activeElement
is generically typed as Element
, which doesn't have a blur
method. You'd need to specify the HTMLSelectElement
type, but it doesn't seem worth pursuing that route since it's more straightforward to just use evt.target
.