Получение значения из <select> с несколькими параметрами в React

81

Способ React установить, какая опция выбрана для поля выбора, состоит в том, чтобы установить valueна самом <select>себе специальную опору , соответствующую valueатрибуту <option>элемента, который вы хотите выбрать. Для multipleвыбора эта опора может принимать вместо этого массив.

Теперь, поскольку это специальный атрибут, мне интересно, какой канонический способ - получить выбранные параметры в той же структуре-массив-значений-параметров, когда пользователь что-то меняет (так что я могу передать его через обратный вызов в родительский компонент и т. д.), поскольку предположительно то же valueсвойство не будет доступно для элемента DOM.

Чтобы использовать пример, с текстовым полем вы должны сделать что-то вроде этого (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} />;
  }
});

Что эквивалентно замене ???для этого компонента множественного выбора?

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>
    );
  }
});
Инклинг
источник

Ответы:

22

С помощью Array.from()и e.target.selectedOptionsвы можете выполнить управляемое множественное выделение:

handleChange = (e) => {
  let value = Array.from(e.target.selectedOptions, option => option.value);
  this.setState({values: value});
}

target.selectedOptions возвращает HTMLCollection

https://codepen.io/papawa/pen/XExeZY

Мендес
источник
Есть идеи, как объединить выбранные параметры из нескольких selectв один массив? Скажите, после того, как вытащили их все через document.querySelectorAll('select')?
Казимир
Обратите внимание, что в то время, когда этот вопрос был задан, у selectedOptionsнего не было хорошей совместимости, и он все еще не поддерживается IE. Однако это был бы современный способ сделать это.
Inkling
107

Так же, как и в любом другом месте, поскольку вы работаете с реальным узлом DOM в качестве цели события изменения:

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);
}
Джонни Бьюкенен
источник
4
Версия CoffeeScript:(option.value for option in e.target.options when option.selected)
1j01 01
64
Версия ES6: [... event.target.options] .filter (o => o.selected) .map (o => o.value)
svachalek
4
Вы также можете разрушить стрелки ES6:[...e.target.options].filter(({selected}) => selected).map(({value}) => value)
Mathieu M-Gosselin
6
RE: Версия ES6, хотя это выглядит правильно, но не работает. event.target.optionsявляется HTMLOptionsCollectionмассивом, а не массивом.
TrueWill 08
3
@zrisher Negative, Призрачный гонщик. HTMLOptionsCollectionне повторяется. Однако Array.fromдо сих пор работает с ним: Array.from(event.target.options).filter(o => o.selected).map(o => o.value)
Bondolin
14

Самый простой способ...

handleChange(evt) {
  this.setState({multiValue: [...evt.target.selectedOptions].map(o => o.value)}); 
}
Джеймсмфридман
источник
Это хорошо, но HTMLCollectionOf<HTMLOptionElement>не массив ... Array.fromХотя вроде работает. stackoverflow.com/a/49684109/29182
Зигги
11

Если вы хотите использовать, refвы можете получить такие выбранные значения:

var select = React.findDOMNode(this.refs.selectRef); 
var values = [].filter.call(select.options, function (o) {
      return o.selected;
    }).map(function (o) {
      return o.value;
    });

Обновление ES6 2018

  let select = this.refs.selectRef;
  let values = [].filter.call(select.options, o => o.selected).map(o => o.value);
Макс Подрезов
источник
1
я буду использовать это для замены своего ответа, так selectedOptionsкак не поддерживается в IE
rambossa
Вот гораздо более чистый, es6 способ сделать это :) [] .filter.call (this.refs.selectRef.options, o => o.selected) .map (o => o.value);
Dg Jacquard
7

Если вы хотите отслеживать выбранные параметры во время заполнения формы:

handleChange(e) {
    // assuming you initialized the default state to hold selected values
    this.setState({
        selected:[].slice.call(e.target.selectedOptions).map(o => {
            return o.value;
        });
    });
}

selectedOptionsпредставляет собой подобный массиву набор / список элементов, связанных с DOM. Вы получаете доступ к нему в целевом объекте события при выборе значений параметров. Array.prototype.sliceи callпозволяет нам создать его копию для нового состояния. Вы также можете получить доступ к значениям таким образом, используя ref (в случае, если вы не фиксируете событие), что было еще одним ответом на вопрос.

Рамбосса
источник
2
Как упоминалось в одном из моих других комментариев, поддержка браузером selectedOptionsкажется довольно отрывочной. Но, наверное, было бы идеальным решением, если бы была поддержка.
Инклинг
1
Ах, правда, похоже, что IE все еще не поддерживает это
rambossa 06
6

Вы действительно можете найти selectedOptionsцель внутри ... нет необходимости перебирать все параметры. Представим, что вы хотите отправить значения вonChange функции, переданной вашему компоненту в качестве реквизита: вы можете использовать следующую функцию onChangeдля вашего множественного выбора.

onSelectChange = (e) => {
    const values = [...e.target.selectedOptions].map(opt => opt.value);
    this.props.onChange(values);
  };
Lanci
источник
В то время, когда был задан этот вопрос, selectedOptionsне было хорошей совместимости. Он по-прежнему не поддерживается Internet Explorer, поэтому не может использоваться, если вам нужна поддержка IE (по крайней мере, без полифилла).
Inkling
3

Следующее сработало для меня

var selectBoxObj = React.findDOMNode(this.refs.selectBox)
var values = $(selectBoxObj).val()
мантийский
источник
1
Правильно, я использовал JQuery для получения нескольких значений.
мантиш
Вам не нужно реагировать на dom или jQuery. Просто получите значение из события
onChange
1

Другой способ сделать это:

handleChange({ target }) {
    this.props.someCallback(
       Array.prototype.slice.call(target.selectedOptions).map(o => o.value)
    )
}
Арал Рока
источник
0

Попробуй это:

dropdownChanged = (event) => {
    let obj = JSON.parse(event.target.value);
    this.setState(
        {
            key: obj.key,
            selectedName: obj.name,
            type: obj.type
        });
}


<select onChange={this.dropdownChanged} >
<option value={JSON.stringify({ name: 'name', key: 'key', type: "ALL" })} >All Projetcs and Spaces</option></select>
Слави Ватахов
источник
Добавьте еще несколько пояснений к своим решениям.
Manmohan_singh