Abrufen des Werts von <Auswahl> mit mehreren Optionen in Reagieren

79

Die Reaktionsmethode zum Festlegen, welche Option für ein Auswahlfeld ausgewählt wird, besteht darin, eine spezielle valueRequisite für sich <select>selbst festzulegen, die dem valueAttribut für das <option>Element entspricht, das Sie auswählen möchten. Für eine multipleAuswahl kann diese Requisite stattdessen ein Array akzeptieren.

Nun , da dies ein spezielles Attribut ist, ich frage mich , was der kanonische Weg ist , um Abrufen der ausgewählten Optionen im gleichen Array-of-Option-Werte-Struktur , wenn der Benutzer der Dinge ändert (so dass ich es durch einen Rückruf an einen passieren kann übergeordnete Komponente usw.), da vermutlich nicht dieselbe valueEigenschaft für das DOM-Element verfügbar ist.

Um ein Beispiel zu verwenden, würden Sie mit einem Textfeld Folgendes tun (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} />;
  }
});

Was ist das Äquivalent ???für diese Mehrfachauswahlkomponente?

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

Antworten:

21

Mit Array.from()und können e.target.selectedOptionsSie ein kontrolliertes Select-Multiple durchführen:

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

target.selectedOptions gibt eine HTMLCollection zurück

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

Mendes
quelle
Irgendwelche Ideen, wie man die ausgewählten Optionen aus mehreren selects in einem Array kombiniert ? Sagen Sie, nachdem Sie sie alle über ergriffen haben document.querySelectorAll('select')?
Casimir
Beachten Sie, dass diese Frage zu dem Zeitpunkt gestellt wurde, selectedOptionskeine gute Kompatibilität aufwies und vom IE immer noch nicht unterstützt wird. Dies wäre jedoch der moderne Weg, dies zu tun.
Inkling
107

Genauso wie anderswo, da Sie mit dem realen DOM-Knoten als Ziel des Änderungsereignisses arbeiten:

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);
}
Jonny Buchanan
quelle
4
CoffeeScript-Version:(option.value for option in e.target.options when option.selected)
1j01
63
ES6-Version: [... event.target.options] .filter (o => o.selected) .map (o => o.value)
svachalek
4
Sie können auch die ES6-Pfeile zerstören:[...e.target.options].filter(({selected}) => selected).map(({value}) => value)
Mathieu M-Gosselin
6
RE: ES6-Version, obwohl das richtig aussieht , funktioniert es nicht. event.target.optionsist ein HTMLOptionsCollection, kein Array.
TrueWill
3
@ Zrisher Negativ, Ghost Rider. HTMLOptionsCollectionist nicht iterierbar. Funktioniert jedoch Array.fromimmer noch damit: Array.from(event.target.options).filter(o => o.selected).map(o => o.value)
Bondolin
13

Einfachster Weg...

handleChange(evt) {
  this.setState({multiValue: [...evt.target.selectedOptions].map(o => o.value)}); 
}
Jamesmfriedman
quelle
Das ist schön, aber HTMLCollectionOf<HTMLOptionElement>kein Array ... Anscheinend Array.fromfunktioniert es aber. stackoverflow.com/a/49684109/29182
Ziggy
11

Wenn Sie verwenden möchten, refkönnen Sie ausgewählte Werte wie folgt erhalten:

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- Update 2018

  let select = this.refs.selectRef;
  let values = [].filter.call(select.options, o => o.selected).map(o => o.value);
Max Podriezov
quelle
1
Ich werde dies auch verwenden, um meine Antwort zu ersetzen, da selectedOptionsdies in IE
Rambossa am
Hier ist eine viel sauberere, es6-Methode :) [] .filter.call (this.refs.selectRef.options, o => o.selected) .map (o => o.value);
Dg Jacquard
7

In dem Fall, dass Sie die ausgewählten Optionen verfolgen möchten, während das Formular ausgefüllt wird:

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

selectedOptionsist eine Array-ähnliche Sammlung / Liste von Elementen, die sich auf das DOM beziehen. Sie erhalten im Ereigniszielobjekt Zugriff darauf, wenn Sie Optionswerte auswählen. Array.prototype.sliceund callermöglicht es uns, eine Kopie davon für den neuen Zustand zu erstellen. Sie können auf diese Weise auch mit einem Verweis auf die Werte zugreifen (falls Sie das Ereignis nicht erfassen). Dies war eine weitere Antwort auf die Frage.

Rambossa
quelle
2
Wie in einem meiner anderen Kommentare erwähnt, selectedOptionsscheint die Browserunterstützung für ziemlich lückenhaft zu sein. Aber es wäre wahrscheinlich die ideale Lösung, wenn die Unterstützung da wäre.
Inkling
1
Ah wahr, es scheint, als ob IE dies immer noch nicht unterstützt
Rambossa
6

Sie können das selectedOptionsInnere des Ziels tatsächlich finden ... Sie müssen nicht alle Optionen durchlaufen. Stellen Sie sich vor, Sie möchten die Werte onChangeals Requisiten an eine an Ihre Komponente übergebene Funktion senden : Sie können die folgende Funktion für die onChangeMehrfachauswahl verwenden.

onSelectChange = (e) => {
    const values = [...e.target.selectedOptions].map(opt => opt.value);
    this.props.onChange(values);
  };
Lanci
quelle
Zu der Zeit, als diese Frage gestellt wurde, selectedOptionshatte keine gute Kompatibilität. Es wird von Internet Explorer immer noch nicht unterstützt und ist daher nicht wirklich verwendbar, wenn Sie IE-Unterstützung wünschen (zumindest ohne Polyfill).
Inkling
3

Folgendes hat bei mir funktioniert

var selectBoxObj = React.findDOMNode(this.refs.selectBox)
var values = $(selectBoxObj).val()
Mantish
quelle
1
Richtig, ich habe JQuery verwendet, um die mehreren Werte abzurufen.
Mantish
Sie müssen weder Dom noch jQuery reagieren. Rufen Sie einfach den Wert aus dem onChange-Ereignis ab
jamesmfriedman
1

Ein anderer Weg, es zu tun:

handleChange({ target }) {
    this.props.someCallback(
       Array.prototype.slice.call(target.selectedOptions).map(o => o.value)
    )
}
Aral Roca
quelle
0

Probier diese:

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>
Slavi Vatahov
quelle
Fügen Sie Ihren Lösungen weitere Erklärungen hinzu.
Manmohan_singh