React: Tie onFocus and onBlur to both an input and a custom dropdown?
Clash Royale CLAN TAG#URR8PPP
React: Tie onFocus and onBlur to both an input and a custom dropdown?
I have an input that users type keywords and a function is triggered to fetch data. The data is then populated in a 'suggested results' div right under the input. All this works great.
I am attempting to make it so when the user clicks inside the input or the div (when visible) at any time, they both have focus. When an item in the div is clicked a function is run depending on the item selected and the menu closes. If they click on anything, not the input or the div, the div should hide, or not show. I've been experimenting with where to place onBlur, onFocus, onClick to no success. Just partials to what I want.
I have a state property that is called 'inputFocused' that is set to false initially, when onFocus runs, it is set to true and that boolean determines if the div is shown.
I've attempted to use onBlur on the input that sets inputFocused to false, which of course hides the div. I removed that and placed it in the div, but because it doesn't have focus, it never runs. Only when I put an onclick that sets the state of inputFocused to false does it hide. But when a user clicks anywhere outside the input, the state doesn't change, onBlur isn't triggered.
class Hello extends React. Component
constructor()
super()
this.state =
inputFocused: false,
visible: false
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
this.select = this.select.bind(this)
onFocus()
this.setState(inputFocused: false)
console.log("FOCUS: ", this.state.inputFocused)
this.setState( inputFocused: !this.state.inputFocused, visible: !this.state.visible )
onBlur()
console.log("Blur: ", this.state.inputFocused)
this.setState( inputFocused: !this.state.inputFocused )
select()
console.log("SELECTED")
this.setState( inputFocused: !this.state.inputFocused, visible: !this.state.visible )
render()
return (
<div>
<div onFocus=this.onFocus>
<input placeholder="MyList"></input>
this.state.inputFocused && this.state.visible ? (
<ul>
<li onClick=() => this.select()>abc</li>
<li onClick=() => this.select()>123</li>
<li onClick=() => this.select()>xyz</li>
</ul>
) : null
</div>
</div>
);
ReactDOM.render(
<Hello initialName="World"/>,
document.getElementById('container')
);
Here is a JSFIDDLE that I've put together to show what I currently have.
1 Answer
1
You don't ever call onBlur
and you're not resetting visible
in onBlur
either.
onBlur
visible
onBlur
onBlur()
console.log("Blur: ", this.state.inputFocused)
this.setState( inputFocused: !this.state.inputFocused, visible: !this.state.visible )
and
<div onFocus=this.onFocus onBlur=this.onBlur>
Here's an updated fiddle: http://jsfiddle.net/sellmeadog/pwujfmk0/
I guess I'm not clear on what you want to happen then? I thought you were trying to ensure that when the component loses focus or an item is selected the popup
div
closes? Did I misunderstand your original ask?– sellmeadog
Aug 10 at 17:17
div
Sorry about not completing my original comment! I didn't mean for it to submit, i wasn't done! It looks rude with just that ha. Yeah, you are right on the nose. That is one thing I want to happen for sure. And I've been able to get that. I am having difficulty when a user clicks anywhere outside of the input or the popup for the popup to also go away. So 2 ways for it to dissapear is 1. when a user selects an item, 2. when user clicks anywhere else.
– jehicks2
Aug 10 at 17:23
Ok... So what problem is handling
onBlur
causing? If you run the updated filled, you'll see that clicking anywhere else hides the div
.– sellmeadog
Aug 10 at 17:28
onBlur
div
True, but selected() doesn't fire when blur is there
– jehicks2
Aug 10 at 17:33
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Yeah, in my example jsfiddle, I left our blur because it was not doing what I wanted.
– jehicks2
Aug 10 at 17:06