Retrieving value from <select> with multiple option in React
The React way to set which option is selected for a select box, is to set a special value
prop on the <select>
itself, corresponding to the value
attribute on the <option>
element you desire to be selected. For a multiple
select this prop can accept an array instead.
Now because this is a special attribute, I'm wondering what the canonical way is to retrieve the selected options in the same array-of-option-values-structure when the user changes things (so I can pass it through a callback to a parent component etc), since presumably the same value
property won't be available on the DOM element.
To use an example, with a text field you would do something like this (JSX):
var TextComponent = React.createClass({
handleChange: function(e) {
var newText = e.target.value;
this.props.someCallbackFromParent(newText);
},
render: function() {
return <input type="text" value={this.props.someText} onChange={this.handleChange} />;
}
});
What is the equivalent to replace ???
for this multiple select component?
var MultiSelectComponent = React.createClass({
handleChange: function(e) {
var newArrayOfSelectedOptionValues = ???;
this.props.someCallbackFromParent(newArrayOfSelectedOptionValues);
},
render: function() {
return (
<select multiple={true} value={this.props.arrayOfOptionValues} onChange={this.handleChange}>
<option value={1}>First option</option>
<option value={2}>Second option</option>
<option value={3}>Third option</option>
</select>
);
}
});
Solution 1:
The same way you do anywhere else, since you're working with the real DOM node as the target of the change event:
handleChange: function(e) {
var options = e.target.options;
var value = [];
for (var i = 0, l = options.length; i < l; i++) {
if (options[i].selected) {
value.push(options[i].value);
}
}
this.props.someCallback(value);
}
Solution 2:
With Array.from()
and e.target.selectedOptions
you can perform a controlled select-multiple:
handleChange = (e) => {
let value = Array.from(e.target.selectedOptions, option => option.value);
this.setState({values: value});
}
target.selectedOptions return a HTMLCollection
https://codepen.io/papawa/pen/XExeZY
Solution 3:
Easiest way...
handleChange(evt) {
this.setState({multiValue: [...evt.target.selectedOptions].map(o => o.value)});
}
Solution 4:
In case you want to use ref
you can get selected values like this:
var select = React.findDOMNode(this.refs.selectRef);
var values = [].filter.call(select.options, function (o) {
return o.selected;
}).map(function (o) {
return o.value;
});
2018 ES6 update
let select = this.refs.selectRef;
let values = [].filter.call(select.options, o => o.selected).map(o => o.value);