carbon-componentscarbon-components-reactGenerally with React we would set focus on a component by getting a ref to the component and calling the focus function on the current ref. Unfortunately, there is no forwardRef and we have no way to get a ref to the input within the ComboBox. I can't seem to figure out a way to inject anything in via props. Is there some way to make this happen?
An example of what I am trying to do:
const Example = () => {
const [adding, setAdding] = useState(false);
return (
<>
<Button
onClick={() => {
setAdding(true);
// HACK to set focus
setTimeout(
() => document.getElementById("test").focus(),
100 // YMMV *shrug*
);
}}
/>
<ComboBox
className={classNames({ [styles.hide]: !adding })}
downshiftProps={{ isOpen: true }}
id="test"
onChange={() => setAdding(false)}
items={[]}
/>
</>
)
}
Basically, when the user clicks a Button the ComboBox will show with the dropdown portion visible. I would also like the text input to have focus so the user can start typing right away. You can see I'm using a setTimeout to manually wait for the box to appear so I can set focus to it. Would love some other more reliable method. Suggestions?
I did find a way around this. You can add the autoFocus property to the ComboBox. I had to tweak the code a bit. Something like the following:
const Example = () => {
const [adding, setAdding] = useState(false);
return (
<>
<Button onClick={() => setAdding(true)} />
{adding &&
<ComboBox
autoFocus
className={classNames({ [styles.hide]: !adding })}
downshiftProps={{ isOpen: true }}
id="test"
onChange={() => setAdding(false)}
items={[]}
/>
}
</>
)
}
Feels like a hack though, and triggers a11y warnings in eslint (though I'm not sure setting focus programmatically is any better in that regard). Thoughts?
I believe now that we have removed the focus trap dependency we should see the expected behavior (ref #5260)
I don't believe this has anything to do with focus trap. I want to be able to get a ref to the underlying input element so I can set focus. Am I missing something?
to my understanding it has always been possible to use refs to access the input (e.g. https://ibm.biz/BdqrgR)
the part about the focus trap external dependency was related to focusing on the input, since that library appeared to be stealing focus
I can't open that link, as I don't have permission or any way to create an account (so far as I can see). However, if you look at the source you will see that the ref to that input is a private class member and not something that I can pass in. What _should_ be happening is that the component should be wrapped in a call to forwardRef (see details here). This way a consumer of the component may pass in their own ref.
If you utilize the forwardRef pattern you could still default to an internal private ref if no ref was passed to the forward. The forwardRef technique is already in place in a number of other components, I just want it added to this one.
Let me know if that doesn't make sense. Thanks!
@supermonkeybrainz Are you an IBMer? If so, feel free to write something to our Slack channel and we'll give you the link.
@supermonkeybrainz converted to code sandbox https://codesandbox.io/s/sweet-bush-kkb65
@asudoh I am not an IBM-er, just an interested user of carbon. :)
@emyarod Thanks for the codesandbox, that clears up what you are trying to say. A creative solution, to be sure. :D
I think the ref solution would be more React-like and straight-forward, but I suppose this will have to do. I do appreciate all the help and responses. Thanks so much!
Oh wait, that still doesn't fix my issue. I need to set focus to the input programmatically, not handle events from the input. Since I only can access the input through the event.target when the input triggers an event I'm not sure this will solve my problem. Back to the drawing board, I guess.
EDIT: See my original post for the example situation I am dealing with.
@supermonkeybrainz You can set a ref to an ancestor node and call .querySelector() to grab a DOM element.
I will go that route, thanks!
@supermonkeybrainz the sandbox was meant to show ref usage, here it is modified for setting focus https://codesandbox.io/s/agitated-tree-tnioe as a workaround
Got it, thanks for the example!
Closing this since it seems the issue has been addressed. Feel free to let me know if that's not the case!
Most helpful comment
@supermonkeybrainz converted to code sandbox https://codesandbox.io/s/sweet-bush-kkb65