React: access data-attribute in <option> tag
Asked Answered
O

3

8

I have this select JSX:

    <select className="form-control" onChange={this.onChange} value={this.props.value}>
      {options}
    </select>

with options being:

var options = this.props.options.map((option) => {
  return (<option key={option.slug} value={option.slug} data-country={option.country} data-continent={option.continent}>{option.value}</option>);
});

But I can't access the selected data-country of the option selected, since the value is accessed by e.target.value, and e.target.dataset is the dataset of the select tag and not the option selected tag:

  onChange: function(e) {
    this.props.onChange(this.props.name, e.target.value, e.target.dataset.continent, e.target.dataset.country);
  },

Is there a fix on this?

Thanks

Octahedral answered 19/2, 2016 at 17:48 Comment(0)
J
7

I would pass around just the slug:

var options = this.props.options.map(option => {
    return (
        <option key={option.slug} value={option.slug}>
          {option.value}
        </option>
    );
});

... and then retrieve the data using the slug:

onChange: function(event, index, value) {
  var option = this.props.options.find(option => option.slug === value);
  this.props.onChange(this.props.name, value, option.continent, option.country);
}

(You'd replace the .find with a forEach or whatever JS you use if not ES6 capable.)

Janitor answered 20/2, 2016 at 23:21 Comment(0)
O
22

I find @bjfletcher even more elegant than mine, but I'll report for the records:

I access the <option> DOM element through e.target.options[e.target.selectedIndex] in the onChange method:

  onChange: function(e) {
    var dataset = e.target.options[e.target.selectedIndex].dataset;
    this.props.onChange(this.props.name, e.target.value, dataset.continent, dataset.country);
  },

Not sure of the compatibility though.

Octahedral answered 22/2, 2016 at 9:33 Comment(2)
This is really terrific, always loved straight JS access to options. Someone can say that this line is longer e.target.options[e.target.selectedIndex], but trust me guys this approach works everywhere in any browser - native support.Thankless
Working in React 17 too.Fantasize
J
7

I would pass around just the slug:

var options = this.props.options.map(option => {
    return (
        <option key={option.slug} value={option.slug}>
          {option.value}
        </option>
    );
});

... and then retrieve the data using the slug:

onChange: function(event, index, value) {
  var option = this.props.options.find(option => option.slug === value);
  this.props.onChange(this.props.name, value, option.continent, option.country);
}

(You'd replace the .find with a forEach or whatever JS you use if not ES6 capable.)

Janitor answered 20/2, 2016 at 23:21 Comment(0)
G
2

I think your best bet would be to use refs.

var options = this.props.options.map((option) => {
  return (<option ref={'option_ref_' + option.slug} ...></option>);
});

onChange: function(e) {
    var selectedOption = this.refs['option_ref_' + e.target.value];
    selectedOption['data-country']; //should work
    ...
},
Gas answered 19/2, 2016 at 18:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.