Recuperando valor de con opción múltiple en React

5 minutos de lectura

avatar de usuario
Indicio

La forma de Reaccionar para establecer qué opción se selecciona para un cuadro de selección, es establecer un especial value apoyar en el <select> mismo, correspondiente a la value atributo en el <option> elemento que desea que sea seleccionado. Para multiple seleccione este accesorio puede aceptar una matriz en su lugar.

Ahora, debido a que este es un atributo especial, me pregunto cuál es la forma canónica de recuperar las opciones seleccionadas en la misma estructura de matriz de valores de opción cuando el usuario cambia cosas (para que pueda pasarlo a través de una devolución de llamada a un componente principal, etc.), ya que presumiblemente lo mismo value La propiedad no estará disponible en el elemento DOM.

Para usar un ejemplo, con un campo de texto harías algo como esto (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} />;
  }
});

¿Cuál es el equivalente a reemplazar? ??? para este componente de selección múltiple?

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

avatar de usuario
jonny buchanan

De la misma manera que lo hace en cualquier otro lugar, ya que está trabajando con el nodo DOM real como destino del evento de cambio:

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

  • Versión de CoffeeScript: (option.value for option in e.target.options when option.selected)

    – 1j01

    1 de julio de 2015 a las 13:33

  • Versión ES6: […event.target.options].filter(o => o.seleccionado).map(o => o.valor)

    – svachalek

    14/08/2015 a las 22:21

  • También puede desestructurar las flechas ES6: [...e.target.options].filter(({selected}) => selected).map(({value}) => value)

    – Mathieu M-Gosselin

    27/09/2016 a las 14:33

  • RE: versión ES6, mientras que aspecto cierto no funciona. event.target.options es un HTMLOptionsCollectionno una matriz.

    – Verdadera Voluntad

    08/08/2018 a las 17:35

  • @zrisher Negativo, Ghost Rider. HTMLOptionsCollection no es iterable. Sin embargo, Array.from todavía funciona con él: Array.from(event.target.options).filter(o => o.selected).map(o => o.value)

    – Bondolina

    16 de julio de 2019 a las 21:42

avatar de usuario
Mendes

Con Array.from() y e.target.selectedOptions puede realizar una selección múltiple controlada:

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

target.selectedOptions devuelve una HTMLCollection

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

  • Cualquier idea sobre cómo combinar las opciones seleccionadas de múltiples selects en una matriz? Di después de agarrarlos a todos a través de document.querySelectorAll('select')?

    – Casimiro

    29 de abril de 2018 a las 16:17

  • Tenga en cuenta que en el momento en que se hizo esta pregunta, selectedOptions no tenía buena compatibilidad y aún no es compatible con IE. Sin embargo, esta sería la forma moderna de hacerlo.

    – Indicio

    25 oct 2020 a las 21:32

La manera más fácil…

handleChange(evt) {
  this.setState({multiValue: [...evt.target.selectedOptions].map(o => o.value)}); 
}

  • Esto es bueno, pero HTMLCollectionOf<HTMLOptionElement> no es una matriz… Aparentemente Array.from aunque funciona stackoverflow.com/a/49684109/29182

    – Ziggy

    14 de julio de 2019 a las 5:18


  • Las opciones seleccionadas ya no son una propiedad de destino en la versión 99.0.4844.51 de Chrome (compilación oficial) (64 bits)

    – Julio Spinelli

    11 de marzo a las 17:41

avatar de usuario
Max Podriezov

En caso de que quieras usar ref puede obtener valores seleccionados como este:

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 actualizar

  let select = this.refs.selectRef;
  let values = [].filter.call(select.options, o => o.selected).map(o => o.value);

avatar de usuario
Miguel Ramos

En caso de que desee realizar un seguimiento de las opciones seleccionadas mientras se completa el formulario:

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 es una colección/lista similar a una matriz de elementos relacionados con el DOM. Obtiene acceso a él en el objeto de destino del evento al seleccionar valores de opción. Array.prototype.slicey call nos permite crear una copia del mismo para el nuevo estado. También podría acceder a los valores de esta manera usando una referencia (en caso de que no esté capturando el evento), que fue otra respuesta a la pregunta.

  • Como mencioné en uno de mis otros comentarios, el soporte del navegador para selectedOptions parece bastante incompleto. Pero probablemente sería la solución ideal si el apoyo estuviera ahí.

    – Indicio

    6 de abril de 2016 a las 3:16


  • Ah, cierto, parece que IE todavía no es compatible con esto.

    – Miguel Ramos

    6 de abril de 2016 a las 11:16

avatar de usuario
Ru Chern Chong

En realidad puedes encontrar el selectedOptions dentro del objetivo… no hay necesidad de iterar sobre todas las opciones. Imaginemos que desea enviar los valores a un onChange función pasada a su componente como accesorios: puede usar la siguiente función en el onChange de su selección múltiple.

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

  • Como mencioné en uno de mis otros comentarios, el soporte del navegador para selectedOptions parece bastante incompleto. Pero probablemente sería la solución ideal si el apoyo estuviera ahí.

    – Indicio

    6 de abril de 2016 a las 3:16


  • Ah, cierto, parece que IE todavía no es compatible con esto.

    – Miguel Ramos

    6 de abril de 2016 a las 11:16

avatar de usuario
mantis

Lo siguiente funcionó para mí

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

  • Correcto, usé JQuery para recuperar los múltiples valores.

    – mantis

    20 de agosto de 2015 a las 7:13

  • No necesita reaccionar dom o jQuery. Simplemente recupere el valor del evento onChange

    – jamesmfriedman

    19 de diciembre de 2017 a las 20:27

¿Ha sido útil esta solución?