How to implement onBlur/onFocus for a div with nested input fields?
Solution 1
Just adding on to this with what I think is the best solution these days.
This ignores blur events by using the Node.contains method to check whether the element is a descendant of that which is already focused.
handleBlur({ currentTarget, relatedTarget }) {
if (currentTarget.contains(relatedTarget)) return;
/* otherwise normal actions to perform on blur */
console.log('blur');
}
handleFocus(e) {
console.log('focus');
}
Solution 2
You may want to ignore extra blur events.
handleBlur(e) {
if (e.target.tagName == "INPUT") {
return;
}
console.log('blur');
}
handleFocus(e) {
console.log('focus');
}
Solution 3
How about splitting the inputs into a single, independent component?
app.js
class Thing extends React.Component {
handleBlur(val, event) {
console.log(val, event);
}
handleFocus(val, event) {
console.log(val, event);
}
data = ['Hello, ', 'Thing'];
render() {
return (
<div tabIndex="1">
{this.data.map((v, i) => <Input value={v} key={i} onFocus={this.handleFocus} onBlur={this.handleBlur} />)}
</div>
);
}
}
Input.js
import React from 'react';
export class Input extends React.PureComponent {
handleF = () => {
this.props.onFocus(this.props.value, 'focus');
}
handleB = () => {
this.props.onBlur(this.props.value, 'blur');
}
render() {
return <input type="text" onFocus={this.handleF} onBlur={this.handleB} />;
}
}
export default Input;
https://codesandbox.io/s/J6o5Ey9Jg
Solution 4
This is from OP comments above, he found the following solution which worked for him (and now me) and posted it in a comment. I am reposting it here for anyone else who might not think to dig through comments.
Basically, I just check on every blur event if e.relativeTarget has e.currentTarget anywhere in the parentElement chain.
Comments
-
dmigo about 2 years
There is a
<div>
and a couple of nested<input>
s.onBlur
fires every time user clicks on one of the<input>
s.
This is a bit frustrating thatonBlur
happens when I hit something inside thediv
. After an hour of searching I still wasn't able to find any good solution.
This sample of code shows what I'm talking about:class Thing extends React.Component { handleBlur(e) { console.log('blur'); } handleFocus(e) { console.log('focus'); } render() { return ( <div onFocus={this.handleFocus} onBlur={this.handleBlur} tabIndex="1"> <div> <input type="text" value="Hello," /> </div> <div> <input type="text" value="Thing" /> </div> </div> ); } }
You may play around with the code over here.
However my ultimate goal is to make this thing working properly.