Home > OS >  How to focus on dynamically added Input field in react
How to focus on dynamically added Input field in react

Time:06-24

On button click I am showing a dialog which have input field. I want to autofocus in that input field. I'm using Material UI Component Dialog & OutlinedInput

const SearchIdDialog: React.FC = () => {
  const [openSearchId, setOpenSearchId] = React.useState<boolean>(false);

  React.useEffect(()=> {
    inputRef.current?.focus();
  }, [openSearchId]);

  const handleClose = () => {
    setOpenSearchId(false);
  };

  const inputRef = React.useRef<HTMLInputElement>(null);

  return (
    <div>
      <Tooltip title="Click to search">
        <Button
          onClick={() => {
            setOpenSearchId(true);
          }}
        >
          Search
        </Button>
      </Tooltip>

      <BootstrapDialog
        onClose={handleClose}
        open={openSearchId}
      >
        <SearchStyle
          inputRef={inputRef}
        />
      </BootstrapDialog>
    </div>
  );
};

I have tried autoFocus prop but its failing. How to wait for input field to render input field first and then focusing it ?

Note: inputRef is used instead of ref because its a mui component which need inputRef. If I use setTimeOut in useEffect and waits for 1 sec and then focus - it works. But I want it naturally.

Sandbox link- https://codesandbox.io/s/react-typescript-forked-f6hg5y?file=/src/SearchIdDialog.tsx

CodePudding user response:

Since autofocus is not working, then you can try with setTimeout.

What I did was to check if openSearchId is true Demo

  React.useEffect(() => {
    if (openSearchId) {
      setTimeout(() => {
        inputRef.current?.focus();
        console.log("focused");
      }, 300);
    }
  }, [openSearchId]);

Does this work for you? You can change the millis of course.

CodePudding user response:

To autofocus on textfield whenever dialog box opens, you can use autoFocus props. It is working. Demo

CodePudding user response:

First do this:

It calls the focus method after the input element is rendered.

 React.useEffect(() => {
    inputRef.current?.focus();
  }, [inputRef.current]);

If it did not work, try using setInterval or setTimeout.

  React.useEffect(()=> {
    const {current} = inputRef 
    
    const interval = setInterval(() => {
        if (current != document.activeElement) {
           current.focus()
        } else {
          clearInterval(interval)
        }
   }, 3000)
    
    return () => clearInterval(interval)
    
  }, [openSearchId]);
 React.useEffect(()=> {
    const {current} = inputRef 
    
    const timeout = setTimeout(() => {
        if (current != document.activeElement) {
           current.focus()
        } else {
          clearTimeout(timeout)
        }
    }, 3000)
    
    return () => clearTimeout(interval)
    
  }, [openSearchId]);

You probably need to restrict the number of times setInterval is called.

Javascript how to clear interval after specific time

CodePudding user response:

Try to wrap your BootstrapDialog componnet in conditional rendering. Something like:

{openSearchId &&
  <BootstrapDialog
    onClose={handleClose}
    open={openSearchId}
  >
    <SearchStyle
      inputRef={inputRef}
    />
  </BootstrapDialog>
 }

Like this autofocus will be triggered right when you open your dialog.

  • Related