React/ReactJS: Dynamic Select/Option
In the first section of this tutorial, you will learn how to add options dynamically to a select/option dropdown in React/ReactJS with array values and with object literal properties.
And in the second section, you will learn how to access custom
data- attributes of a selected element in
a select/option dropdown.
We will proceed with examples.
Dynamic Dropdown
Create two state variables countries and
colours to store the details of few
countries and colours as an array and an object respectively. Inside
the constructor(), initialize the
countries state variable to an empty
array [] and the
colours variable to an empty object
{}.
constructor(props) {
super(props);
this.state = {
countries: [],
colours: {}
};
}
Array
The countries state variable is an
array, and its elements are assigned inside the
componentDidMount() lifecycle method. If
you have an API, you can call it and do the assignments of the
response data here.
componentDidMount() {
this.setState({
countries: [
{id: 'AFG', name: 'Afghanistan'},
{id: 'ALA', name: 'Aland Islands'},
{id: 'ALB', name: 'Albania'}
]
});
}
Now inside the render() method, we make
use of the
Array.map()
method, which calls the callback function once for each element and
returns a newly constructed array from the results.
render() {
const { countries } = this.state;
let countriesList = countries.length > 0
&& countries.map((item, i) => {
return (
<option key={i} value={item.id}>{item.name}</option>
)
}, this);
return (
<div>
<select>
{countriesList}
</select>
</div>
);
}
Here is the complete component.
import React, { Component } from 'react';
class Countries extends React.Component {
constructor(props) {
super(props);
this.state = {
countries: [],
colours: {}
};
}
componentDidMount() {
this.setState({
countries: [
{id: 'AFG', name: 'Afghanistan'},
{id: 'ALA', name: 'Ă…land Islands'},
{id: 'ALB', name: 'Albania'}
]
});
}
render () {
const { countries } = this.state;
let countriesList = countries.length > 0
&& countries.map((item, i) => {
return (
<option key={i} value={item.id}>{item.name}</option>
)
}, this);
return (
<div>
<select>
{countriesList}
</select>
</div>
);
}
}
export default Countries;
Literal Object
Just like the countries state variable
in the above section, the colours state
variable (which is an object) is also assigned the key-value pairs
inside the componentDidMount() method.
componentDidMount() {
this.setState({
colours: {
"#ff0000": "Red",
"#00ff00": "Green",
"#0000ff": "Blue"
}
});
}
Inside render(), we first make use of
the
Object.keys()
method to obtain the keys of the
colours object as an array.
So, Object.keys(colours) will return the
array ["#ff0000", "#00ff00", "#0000ff"].
Now on this newly formed array, we apply the
map() method and return the
<option/> elements as we did
above.
render() {
const { colours } = this.state;
let coloursList = Object.keys(colours).map((k) => {
return (
<option key={k} value={k}>{colours[k]}</option>
)
}, this);
return (
<div>
<select>
{coloursList}
</select>
</div>
);
}
Access/Get Custom data- Attribute Values
Accessing the data- attributes of an
element belong to the realm of Vanilla JavaScript. For the sake of
simplicity, here we will consider static select/option dropdowns.
In a typical select/option dropdown, the usual required value to be
sent when an option is selected is set to the
value attribute. For example, in a
typical country list dropdown, you might have set the option values
to respective ISO 3166 codes as shown below
<select>
<option value="AFG">Afghanistan</option>
<option value="ALA">Aland Islands</option>
<option value="ALB">Albania</option>
</select>
But often we need to pass along additional information besides the usual value. For example, in the above case, you might need to pass along the ISD code too. Take another example. Consider a dropdown list of movies. You might have set the values to movie names but at the same time need to pass along the release year. There are many such cases we come across when we develop an application.
Such additional data are best stored by
custom data attributes. An HTML element can have any number of custom attributes with any
value. Their name starts with data-,
followed by at least one character after the hyphen which is/are not
uppercased. For example, in a typical country list dropdown (as in
the example above), if you have set the values to respective ISO
3166 code, you can store their ISD codes in a custom attribute like
data-isd.
<select>
<option data-isd="+93" value="AFG">Afghanistan</option>
<option data-isd="+358" value="ALA">Aland Islands</option>
<option data-isd="+355" value="ALB">Albania</option>
</select>
In a dropdown list of movies, if you have set the values to movie
names, their respective release years can be stored in a custom data
attribute like data-year.
<select>
<option data-year="2009" value="District 9">District 9</option>
<option data-year="2010" value="Predators">Predators</option>
<option data-year="2002" value="Star Trek: Nemesis">Star Trek: Nemesis</option>
</select>
Now that we have assigned the custom data attributes, how do we
access them? Via the
dataset
property available on the
HTMLElement
interface. This is what you will learn in the first part of this
tutorial: how to fetch custom
data- attributes set in the
<option/> elements in
React/ReactJS.
We pick the dropdown list of our first example, the country dropdown
list. We assign a handler called
selectCountry() to the
onChange event in the
<select/> element.
<select onChange={this.selectCountry}>
<option data-isd="+93" value="AFG">Afghanistan</option>
<option data-isd="+358" value="ALA">Aland Islands</option>
<option data-isd="+355" value="ALB">Albania</option>
</select>
We define selectCountry() as a method
inside the class constructor.
constructor(props) {
super(props);
this.selectCountry = this.selectCountry.bind(this);
}
Now here is the most important part. The custom
data-isd attribute we stored on the
<option/> elements may be accessed
via its dataset property as shown below.
Note carefully the last line. The
data-isd attribute is accessed as
dataset.isd.
selectCountry = (e) => {
let idx = e.target.selectedIndex;
let dataset = e.target.options[idx].dataset;
console.log('ISD Code: ', dataset.isd);
}
On select of Albania, the above
selectCountry() method logs in the
browser's console the value stored in the custom
data-isd attribute.