so, have custom search , select component renders input , results list wrapped in parent container:
<div classname='wrapper'> <input /> <div classname='results'> <div>result item</div> <div>result item</div> <div>result item</div> <div>result item</div> <div>result item</div> </div> </div>
what i'm trying achieve when user focuses on input
results list div appears. i'm achieving using piece of state - isexpanded
. so, use onfocus method of input:
<input onfocus={this.handlefocus} />
and function:
handlefocus = () => { this.setstate({ isexpanded: true }); }
that works great. issue i'm having getting close @ proper moment. should close if user physically clicks outside of the wrapper
div
. when need remain open:
- if user clicks on of result items
- if user focused on input, clicks result item
- if user clicks on result item, focuses on input
so, interaction within wrapper
div should remain open.
in order attempt achieve this, i've put blur event around wrapper:
<div classname='wrapper' tabindex='1' onblur={this.handleblur}> ... </div>
and function
handleblur = () => { this.setstate({ isexpanded: false }); }
the problem is, when click item or focusing on input takes away focused wrapper
event fires, should, cannot prevent firing when don't want to.
i've tried using document.activeelement
mixed reactdom.finddomnode
compare active element, still not working. ideas?
here basic example of i'm trying achieve (it uses different function binding method, point still stands):
class searchandselect extends react.component { constructor() { super(); this.state = { isexpanded: false } this.handleblur = this.handleblur.bind(this); this.handlefocus = this.handlefocus.bind(this); } handleblur() { this.setstate({ isexpanded: false }) } handlefocus() { this.setstate({ isexpanded: true }) } render(){ return( <div classname='wrapper' tabindex='1' onblur={this.handleblur}> <input onfocus={this.handlefocus} /> {this.state.isexpanded && <div>results</div>} </div> ); } } reactdom.render(<searchandselect />, document.getelementbyid('container'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="container"></div>
you can want blur ignored if mouse down within wrapper when blur event occurs. i've used this.ignoreblur indicate if blur should ignored - have not used state don't want or need cause re-render. i've included moving out of wrapper reset ignoreblur in case mouse down never mouse event wrapper , leave ignoreblur permanently true!
<div classname='wrapper' onmousedown={this.setignoreblur} onmouseup={this.clearignoreblur} onmouseout={this.clearignoreblur} onblur={this.handleblur}> <input /> <div classname='results'> <div>result item</div> <div>result item</div> <div>result item</div> <div>result item</div> <div>result item</div> </div> </div> setignoreblur = () => { this.ignoreblur = true; } clearignoreblur = () => { this.ignoreblur = false; } handleblur = () => { if (this.ignoreblur) return; this.setstate({ isexpanded: false }); }
i updated fiddle: https://jsfiddle.net/jwm6k66c/2474/
Comments
Post a Comment