简体   繁体   中英

how to set focus on input inside loop of react js

I am trying to set focus on input whose parent div is clicked, am able to get the parent div event, I don't know how ref can help me inside this loop, any help will be appreciated.

select = (e,datas) => {
  selected = parseInt(e);
  this.setState({active: selected});
}

HTML Below

Object.keys(this.state.cdata).map((id,val) => {
  return (
   <div 
     key={val} 
     onClick={this.select.bind(this, this.state.cdata[id].id)}
    >
     <div className={(this.state.cdata[id].id === this.state.active)?'country-edit':''}>
       <i className="fa fa-globe" aria-hidden="true"></i>
       <div className="country-name">{this.state.cdata[id].name}</div>
         <input 
           type="text"
           value={this.state.cdata[id].name}
           className="hidden"
           onChange={this.edit}
           onKeyPress={this.check}
         />
       </div>
     </div>
   )
})

I am trying to set focus on input whose parent div is clicked

You can do that using the event:

select = (e,datas) => {
    //set focus to input
    e.target.querySelector('input').focus();
    selected = parseInt(e);
    this.setState({active: selected});
}

Edit

Use a closure to get the synthetic event:

select(datas){
  return function(e){
    e.target.querySelector("input").focus();
    //rest of code
  }
}

When you pass the method select , execute it so it returns the function:

onClick={this.select().bind(this, myData)}

Might not be the best of implementation but should work.

Target element can be any of the child, so we need to figure out the correct input element no matter which child is clicked. To do that I am assigning a data-index attribute to all the elements that could be associated with the event.

And then maintain an instance variable inputElements which stores the DOM node for each input element.

NOTE Make sure to set this instance variable to [] . I am setting it inside the map function but need to set it either in the constructor of any place relevant.

Unnecessarily storing too many DOM nodes is not so good but then again, it's just a matter of 3-4 elements. So, it should be okay.

Please give this a try and let me know if it requires any modifications.

Object.keys(this.state.cdata).map((id,val) => {
  // This should be outside, place it somewhere relevant.
  this.inputElements = [];
  return (
   <div 
     key={val}
     data-index={val}
     onClick={this.select.bind(this, this.state.cdata[id].id)}
    >
     <div 
       data-index={val}
       className={(this.state.cdata[id].id === this.state.active)?'country-edit':''}
     >
       <i data-index={val} className="fa fa-globe" aria-hidden="true"></i>
       <div data-index={val} className="country-name">{this.state.cdata[id].name}</div>
         <input 
           ref={(elem) => { this.inputElements[val] = elem }}
           type="text"
           value={this.state.cdata[id].name}
           className="hidden"
           onChange={this.edit}
           onKeyPress={this.check}
         />
       </div>
     </div>
   )
})

And then your event handler will figure out the index from the target element because each element has the data available as to which particular index it it supposed to work on.

select(datas, e) {
  const clickableIndex = e.target.dataset.index;
  if(clickableIndex) {
    this.inputElements[clickableIndex].focus();
    this.setState({active: clickableIndex});
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM