最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Blur Material UI Select component on the onChange event - Stack Overflow

programmeradmin2浏览0评论

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 element

  • Through the document.activeElement: this gives me an error, apparently property blur 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 element

  • Through the document.activeElement: this gives me an error, apparently property blur 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(); or evt.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
 |  Show 1 more ment

2 Answers 2

Reset to default 4

inspired 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.

发布评论

评论列表(0)

  1. 暂无评论