javascript - React Component "closing" when lost focus - Stack Overflow

I'm trying to create a select2 style ponent in React.I have got 90% functionality down, the one bi

I'm trying to create a select2 style ponent in React.

I have got 90% functionality down, the one bit I just can't fathom is hiding the result box when the user clicks away

The render method is:

render() {
    let resultBlock;

    if (this.state.showSearch) {
        resultBlock = (
            <div className="search-input-container" onBlur={this.onBlur}>
                <div className="search-input-results">
                    <input 
                        type="text" 
                        name={this.props.name}
                        placeholder={this.props.placeholder}
                        className="form-control"
                        onChange={this.inputKeyUp}
                        autoComplete="false" />
                    <ul>
                        {this.state.items.map((item, i) => <li key={i} data-value={item.id} onClick={this.itemSelected} className={item.isSelected ? 'selected' : ''}>{item.text}</li>)}
                    </ul>
                </div>
            </div>
        );
    }

    let displayBlock;
    if (this.props.value.text) {
        displayBlock = this.props.value.text;
    } else {
        displayBlock = <span className="placeholder">{this.props.placeholder}</span>;
    }

    return (
        <div className="form-group">
            <label htmlFor={this.props.name}>{this.props.label}:</label>

            <div className="form-input">
                <div className="searchable-dropdown" onClick={this.revealSearch}>
                    {displayBlock}
                    <div className="arrow"><i className="fa fa-chevron-down" aria-hidden="true" /></div>
                </div>
                {resultBlock}
            </div>
        </div>
    );
}

I've tried moving onBlur={this.onBlur} around, but it only fires if the <input... had focus before one clicked away.

It can't be that plicated, the only approach I thought of, is attaching a global click handler to the page, and diff'ing clicks to understand if a user hasn't clicked on my ponent. But this seems over engineered.

How can this be achieved?

I'm trying to create a select2 style ponent in React.

I have got 90% functionality down, the one bit I just can't fathom is hiding the result box when the user clicks away

The render method is:

render() {
    let resultBlock;

    if (this.state.showSearch) {
        resultBlock = (
            <div className="search-input-container" onBlur={this.onBlur}>
                <div className="search-input-results">
                    <input 
                        type="text" 
                        name={this.props.name}
                        placeholder={this.props.placeholder}
                        className="form-control"
                        onChange={this.inputKeyUp}
                        autoComplete="false" />
                    <ul>
                        {this.state.items.map((item, i) => <li key={i} data-value={item.id} onClick={this.itemSelected} className={item.isSelected ? 'selected' : ''}>{item.text}</li>)}
                    </ul>
                </div>
            </div>
        );
    }

    let displayBlock;
    if (this.props.value.text) {
        displayBlock = this.props.value.text;
    } else {
        displayBlock = <span className="placeholder">{this.props.placeholder}</span>;
    }

    return (
        <div className="form-group">
            <label htmlFor={this.props.name}>{this.props.label}:</label>

            <div className="form-input">
                <div className="searchable-dropdown" onClick={this.revealSearch}>
                    {displayBlock}
                    <div className="arrow"><i className="fa fa-chevron-down" aria-hidden="true" /></div>
                </div>
                {resultBlock}
            </div>
        </div>
    );
}

I've tried moving onBlur={this.onBlur} around, but it only fires if the <input... had focus before one clicked away.

It can't be that plicated, the only approach I thought of, is attaching a global click handler to the page, and diff'ing clicks to understand if a user hasn't clicked on my ponent. But this seems over engineered.

How can this be achieved?

Share Improve this question asked Dec 20, 2016 at 9:45 Callum LiningtonCallum Linington 14.4k14 gold badges80 silver badges156 bronze badges 4
  • 2 "attaching a global click handler to the page" - this is exactly how it should be done. – dfsq Commented Dec 20, 2016 at 9:47
  • you serious?! right.... to what object, window, document? – Callum Linington Commented Dec 20, 2016 at 9:48
  • @CallumLinington, window would work – Chris Commented Dec 20, 2016 at 9:55
  • Can I use event.preventDefault() in the window click handler to stop unwanted clicks? I should also detach the event, this should be done in ponentWillUnmount? – Callum Linington Commented Dec 20, 2016 at 10:00
Add a ment  | 

2 Answers 2

Reset to default 5

I achieved this functionality by:

Putting this in the constructor:

this.windowClick = this.windowClick.bind(this);

(From what dfsq said) Put this in ponentDidMount:

if (window) {
    window.addEventListener('click', this.windowClick, false);
}

This event handler:

windowClick(event) {
    event.preventDefault();

    if (event.target.classList.contains('searchable-marker')) {
        return;
    } else {
        this.setState({
            showSearch: false
        });
    }
}

Where searchable-marker is just a class I put on all the div's, ul's, li's and inputs to make sure that if I clicked one of these, it wouldn't close the the box.

Adding the unmount:

ponentWillUnmount() {
    window.removeEventListener('click', this.windowClick, false);
}

what you can try doing is onBlur you could change the value of this.state.showSearch = false and when this condition is satisfied add a className="hide" (hide{display: none}) by creating a custom function which returns a classname as a string.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745456656a4628517.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信