javascript - How to hide a div when input or child is not focused using React? -


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