Reputation: 1487
How can I set the focus on a Material UI TextField component?
componentDidMount() {
ReactDom.findDomNode(this.refs.myControl).focus()
}
I have tried the above code, but it does not work.
Upvotes: 122
Views: 148486
Reputation: 1183
For those on the latest version of React 18 and MUI (Dec 2023)
and are using a Dialog Box.
You don't need any ref or input ref solutions.
You'll need to set disableRestoreFocus
on the parent dialog && then set autoFocus
as usual on the TextField
.
<Dialog
open={showNewAccountDialog}
onClose={() => setShowNewAccountDialog(false)}
disableRestoreFocus={true}
>
...
<TextField autoFocus {...otherProps}/>
</Dialog>
Here's an issue that is currently being tracked: https://github.com/mui/material-ui/issues/33004#issuecomment-1473299089
Upvotes: 8
Reputation: 31
Update 2023 - with MUI v.5.14.8, you can use focused
prop.
This prop sets the 'focused' attribute to the input element.
<TextField
focused
/>
Upvotes: 3
Reputation: 2049
You can use the autoFocus
prop:
<TextField value="some value" autoFocus />
It sets the autofocus
attribute on the <input>
element.
Upvotes: 111
Reputation: 3361
For React 16.8.6, you should use the inputRef
property of TextField to set focus.
<TextField
inputRef={input => input && input.focus()}
/>
Material UI doc says:
inputRef
: Use this property to pass a ref callback to the native input component.
The ref
prop wouldn't work. It gives a reference to the root DOM element of the TextField which is the parent of the <input>
element.
Upvotes: 146
Reputation: 1
For TypeScript version in MUI 5 I had to use inner elements of TextField such a way
const inputRef = useRef(null);
...
useEffect(() => {
const timeout = setTimeout(() => {
if (inputRef && inputRef.current) {
(((inputRef.current as unknown as HTMLElement)?.firstChild as HTMLElement)?.firstChild as HTMLElement)?.focus();
}
}, 100);
return () => {
clearTimeout(timeout);
};
}, [open]);
...
<TextField ref={inputRef}/>
Upvotes: 0
Reputation: 2365
I had a similar problem where the input field didn't regain focus after I've modified its contents with external controls (an emoji picker). I ended up with this brute workaround hook:
const useEnforceFocusTextField = (textFieldRef: React.RefObject<HTMLInputElement>) => {
const [enforcedRerender, setEnforcedRerender] = useState(false);
React.useEffect(() => {
textFieldRef.current?.focus();
const timeout = setTimeout(() => {
textFieldRef.current?.focus();
}, 100);
return () => clearTimeout(timeout);
}, [enforcedRerender]);
return () => setEnforcedRerender((n) => !n);
};
From the outside, you call utilize this hook in the following manner:
const textFieldRef = useRef<HTMLInputElement>(null);
...
// enforceFocus() can be called in any callback to set the focus to the textfield
const enforceFocus = useEnforceFocusTextField(textFieldRef);
...
return <TextField inputRef={textFieldRef} ... />
Upvotes: 0
Reputation: 59
useRef
hook simple example:
const focusMe_Ref = useRef(null); // 1. create
useEffect(() => {
focusMe_Ref.current.focus(); // 2. startup
}, []);
...
<TextField
inputRef={focusMe_Ref} // 3. will focused
...
/>
Upvotes: 4
Reputation: 472
add this propery to your TextField
component :
inputRef={(input) => input?.focus()}
Upvotes: 8
Reputation: 51
const handleClick = () => {
inputRef.current.firstChild.focus();
inputRef.current.firstChild.placeholder = '';
}
<InputBase
value={value}
ref={inputRef}
placeholder="search" />
<Button onClick={handleClick}>Click</Button>
Upvotes: 3
Reputation: 1540
I am using this solution, works for text fields inspired by https://gist.github.com/carpben/de968e377cbac0ffbdefe1ab56237573
const useFocus = (): [any, () => void] => {
const htmlElRef: MutableRefObject<any> = useRef<HTMLDivElement>();
const setFocus = (): void => {
if (!htmlElRef || !htmlElRef.current) return
const div = htmlElRef.current as HTMLDivElement
if (!div) return
const input = div.querySelector("input")
if (input) input.focus()
}
return [htmlElRef, setFocus];
};
export function MyComp() {
const [ref, setFocus] = useFocus()
// use setFocus() to focus the input field
return <Input ref={ref} />
}
Upvotes: 0
Reputation: 1845
This will focus the component every time it renders. Other solutions I tried only focus the element an initial time.
const inputRef = React.useRef<HTMLInputElement>();
useEffect(() => {
inputRef.current?.focus();
}, [inputRef.current]);
const setTextInputRef = (element: HTMLInputElement) => {
inputRef.current = element;
};
return (
<TextField
inputRef={setTextInputRef}
/>
Upvotes: 9
Reputation: 227
This code is actually good, but has a drawback, on every render it's going to create a new function. It easily can be solved using useCallback
<TextField
inputRef={input => input && input.focus()}
/>
Should be
const callbackRef = useCallback((inputElement) => {
if (inputElement) {
inputElement.focus();
}
}, []);
...
<TextField
inputRef={callbackRef}
/>
Upvotes: 2
Reputation: 176
If you are using material-ui TextField and react functional component, you can pass inputRef in your TextField component. The trick here is the if condition if(input != null)
.
<TextField
variant="filled"
inputRef={(input) => {
if(input != null) {
input.focus();
}
}}
/>
Here is an working example for you. CodeSandBox- Material-ui-TextFieldFocus
Upvotes: 11
Reputation: 1
For a material ui TextField you need to input the props for autoFocus in a inputProps object like this.
<TextField inputProps={{ autoFocus: true }} />
Upvotes: -1
Reputation: 8294
AlienKevin is correct ( pass a ref callback to "TextField.inputProps" ), but you can also save the element reference on your "this" object, so that you can set focus later. Here is an example in Coffeescript:
TextField
inputProps:
ref: (el)=>
if el?
@input_element = el
Button
onClick:=>
@input_element.focus()
Upvotes: -2
Reputation: 6950
autoFocus
was also not working for me, perhaps since this is a component that's not mounted when the top-level component loads. I had to do something a lot more convoluted to get it to work:
function AutoFocusTextField(props) {
const inputRef = React.useRef();
React.useEffect(() => {
const timeout = setTimeout(() => {
inputRef.current.focus();
}, 100);
return () => {
clearTimeout(timeout);
};
}, []);
return <TextField inputRef={inputRef} {...props} />;
}
Note that for some reason it does not work without the setTimeout
. For more info see https://github.com/callemall/material-ui/issues/1594.
Upvotes: 39