Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React - ul with onBlur event is preventing onClick from firing on li

Tags:

I've created a mobile dropdown menu that toggles open and closed based on state. Once it's open, I would like the user to be able to close the dropdown by clicking anywhere outside the ul.

I'm setting the tabIndex attribute on the ul to 0, which gives the ul "focus". I've also added an onBlur event to the ul that triggers the state change (dropdownExpanded = false) that hides the ul.

<ul tabIndex="0" onBlur={this.hideDropdownMenu}>   <li onClick={this.handlePageNavigation}>Page 1</li>   <li onClick={this.handlePageNavigation}>Page 2</li>   <li onClick={this.handlePageNavigation}>Page 3</li> </ul> 

However, when I implement this fix, the onClick events that I have on each li element fail to fire.

I know something is going on with the event bubbling, but I am at a lose as to how to fix it. Can anyone help?

NOTE:

I know you can create a transparent div below the ul that spans the entire viewport and then just add an onClick even to that div that will change the state, but I read about this tabIndex/focus solution on Stack Overflow and I'd really like to get it working.

Here is a more complete view of the code (the dropdown is for users to select their home country, which updates the ui):

const mapStateToProps = (state) => {     return {         lang: state.lang     } }  const mapDispatchToProps = (dispatch) => {     return { actions: bindActionCreators({ changeLang }, dispatch) }; }  class Header extends Component {     constructor() {         super();          this.state = {           langListExpanded: false         }          this.handleLangChange = this.handleLangChange.bind(this);         this.toggleLangMenu = this.toggleLangMenu.bind(this);         this.hideLangMenu = this.hideLangMenu.bind(this);      }      toggleLangMenu (){       this.setState({         langListExpanded: !this.state.langListExpanded       });     }      hideLangMenu (){       this.setState({         langListExpanded: false       });     }       handleLangChange(e) {         let newLang = e.target.attributes['0'].value;         let urlSegment = window.location.pathname.substr(7);          // blast it to shared state         this.props.actions.changeLang( newLang );         // update browser route to change locale, but stay where they are at         browserHistory.push(`/${ newLang }/${ urlSegment }`);         //close dropdown menu         this.hideLangMenu();     }      compileAvailableLocales() {         let locales = availableLangs;         let selectedLang = this.props.lang;          let markup = _.map(locales, (loc) => {             let readableName = language[ selectedLang ].navigation.locales[ loc ];              return (                 <li                   key={ loc }                   value={ loc }                   onMouseDown={ this.handleLangChange }>                     { readableName }                 </li>             );         });          return markup;     }       render() {         let localeMarkup = this.compileAvailableLocales();         return (             <section className="header row expanded">               < Navigation />             <section className="locale_selection">                   <button                     className="btn-locale"                     onClick={this.toggleLangMenu}>                     {this.props.lang}                   </button>                   <ul                       className={this.state.langListExpanded ? "mobile_open" : " "}                       value={ this.props.lang }                       tabIndex="0"                       onBlur={this.hideLangMenu}>                   >                       { localeMarkup }                   </ul>                  </section>             </section>         )     } } 
like image 240
Jordan England-Nelson Avatar asked May 23 '17 18:05

Jordan England-Nelson


People also ask

How do you turn off onBlur event in react?

In this situation, call event. preventDefault() on the onMouseDown event. onMouseDown will cause a blur event by default, and will not do so when preventDefault is called. Then, onClick will have a chance to be called.

Why is onBlur not fired?

You can add tabIndex={0} to outermost div in order to dismiss keyboard from input. If the element that has the onBlur effect and tabindex is created onClick of another element, it does not automatically gets focus when it appears. Thus, you may need to focus it using element. focus() after creating the element.

Can I use onBlur instead of onChange?

onBlur must be used instead of onchange, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users #67.

What triggers onBlur?

The onblur event occurs when an object loses focus. The onblur event is most often used with form validation code (e.g. when the user leaves a form field). Tip: The onblur event is the opposite of the onfocus event.


1 Answers

Try using onMouseDown instead of onClick.

like image 200
Stephen L Avatar answered Oct 10 '22 15:10

Stephen L