Skip to content

Instantly share code, notes, and snippets.

@AshCoolman
Created March 19, 2018 18:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AshCoolman/1359c2f988fbbc12df5d24084d2cc62b to your computer and use it in GitHub Desktop.
Save AshCoolman/1359c2f988fbbc12df5d24084d2cc62b to your computer and use it in GitHub Desktop.
React Component to onBlur, only when leaving component

[PROOF OF CONCEPT] For when you want "tabbable" children (e.g. in Date selector composed of a textfield for Day, Month and year) but only want to perform validation on blur-entire-component not each Textfield

class BlurCapturer extends React.Component {
    static propTypes = {
        name: PropTypes.string.isRequired,
        onBlur: PropTypes.func,
        children: PropTypes.node,
    }
    setListeners = (ref) => {
        this.el = findDOMNode(ref);
        this.el.addEventListener('blur', this.handleBlur, true);
    }

    handleBlur = (event) => {
        if (event.target !== this.el) {
            event.preventDefault();
            event.stopPropagation();
        }
        console.log({
            current: event.currentTarget && event.currentTarget.getAttribute('name'),
            related: event.relatedTarget && event.relatedTarget.getAttribute('name'),
            target: event.target && event.target.getAttribute('name'),
        });

        setTimeout(() => { // Needs timeout https://stackoverflow.com/a/121708/225813
            if (this.props.onBlur && !this.el.contains(document.activeElement)) {
                const inputIterator = this.el.querySelectorAll('input').values();
                const values = [...inputIterator].map(input => input.value);
                this.props.onBlur(this.props.name, values);
            }
        });
    }

    render() {
        return (
            <Padded ref={this.setListeners} {...this.props}>
                {this.props.children}
                <input name="day" />
                <input name="month" />
                <input name="year" />
            </Padded>
        );
    }
}

Usage:

<BlurCapturer name="outer" onBlur={console.log}>
    <input name="label" />
</BlurCapturer>

Note: works with children

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment