How to manually open select in React

wwayne
3 min readAug 15, 2015

In my recent project, I need to support opening the select manually, to be exactly, the users only want to use keyboard to control the select:

We use React as our front-end framework and I was disappointed when I got nothing related on google, so I decided to do it myself with some original JS knowledge.

Requirements:

  1. open <select> when it get focused
  2. switch to next <select> when selecting an <option>
  3. every <select> can search specific <option>

Open <select> when it get focused

In the past, it is easy to do this via Jquery, but React is not designed to react with DOM, so I have to find another way to implement this. Finally I find the attribute of <select> named “size” can satisfy my requirements

<select tabIndex={1} ref="yearSelect" 
onFocus={(e)=>{e.target.size=”6"}}
onBlur={(e)=>{e.target.size=”0"}}>
{options}
</select>

changing the size attribute can manually toggle a <select> status, the <select> close when it’s size is 0, and open when the size is bigger than 0, the number here means how many <option> in the visible area.

Switch to next <select> when selecting an <option>

There are three ways for an user to select an option, they are: mouse Click, keyboard Enter, keyboard Tab.

Click is only need to bind an event on an <option>, then use the ref to find the parent <select> and blur it.

Tab will automatically choose the option then switch to the next <select>, so no extra functions needed here.

Enter need you to bind a event listener on <select>, and in my project, I use tabIndex to judge which is next focus target

componentDidMount() {
// Bind event listener on every <select>
let selects = document.querySelectorAll(“select”);
for(let i = 0 ; i < selects.length; i++) {
selects[i].addEventListener(“keydown”, this.listenSelect.bind(this), false);
}
}
componentWillUnmount() {
// Unbind listeners
let selects = document.querySelectorAll(“select”);
for(let i = 0 ; i < selects.length; i++) {
selects[i].removeEventListener(“keydown”, this.listenSelect.bind(this), false);
}
}
listenSelect(e) {
// keyboard is enter
if(e.keyCode === 13) {
let allSelects = document.querySelectorAll(“select”);
let currentIndex = e.target.tabIndex;

for (let i=0; i<allSelects.length; i++) {

// Find the next element with next tab index
if(allSelects[i].tabIndex === currentIndex + 1 ) {
allSelects[i].focus();
return;
}

// If current element is the last element with tabIndex, just blur
if(i === allSelects.length-1) {
e.target.blur();
}
}
}

Every <select> can search specific <option>

For original <select> element in the HTML, it supports search, after you open a <select> you can type a specific value then it will turn to that option. But it not only doesn’t have a input for users to type, but also not accurate when you repetitive typing (type some thing first, then delete and type some other things).

The original search function is enough for me, so I didn’t deep into it( I kew it will take a lot of time).

If you want to do some other special things with <select> in React, I recommend you can take a look at this react-select.

That’s it, welcome comments if you have any question.

--

--