Отримання значення з <select> з декількома опціями в React


81

Спосіб реагування, щоб встановити, який параметр буде обраний для поля вибору, полягає у встановленні спеціального 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


Будь-які ідеї щодо того, як об’єднати вибрані параметри з декількох selects в один масив? Скажіть, схопивши їх усіх через 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,

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)
Матьє М-Госселін

6
RE: версія ES6, хоча, здається, це не працює. event.target.optionsє HTMLOptionsCollection, а не масив.
TrueWill

3
@zrisher Negative, Ghost Rider. HTMLOptionsCollectionне є ітераційним. Однак Array.fromвсе ще працює з цим: Array.from(event.target.options).filter(o => o.selected).map(o => o.value)
Бондолін,


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;
    });

2018 оновлення ES6

  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дозволяє нам створити його копію для нової держави. Ви також можете отримати доступ до значень таким чином, використовуючи посилання (якщо ви не фіксуєте подію), що було іншою відповіддю на запитання.


2
Як згадувалося в одному з моїх інших коментарів, підтримка браузера selectedOptionsздається досить схематичною. Але це, мабуть, було б ідеальним рішенням, якби підтримка була там.
Inkling

1
Правда, здається, IE все ще цього не підтримує
rambossa

6

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

onSelectChange = (e) => {
    const values = [...e.target.selectedOptions].map(opt => opt.value);
    this.props.onChange(values);
  };

На той час, коли було задано це запитання, selectedOptionsвін не мав хорошої сумісності. Він все ще не підтримується Internet Explorer, тому насправді не корисний, якщо вам потрібна підтримка IE (принаймні без полізаповнення).
Inkling

3

У мене працювало наступне

var selectBoxObj = React.findDOMNode(this.refs.selectBox)
var values = $(selectBoxObj).val()

1
Правильно, я використовував JQuery для отримання кількох значень.
mantish

Вам не потрібна реакція dom або jQuery. Просто отримайте значення з події onChange
jamesmfriedman

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.