10

I try to handle a multiple form select option, in ReactJS. I have tried to be inspire of javascript classic code to handle that, but I fail.

My code just don't send me the values selected. How handle that ?

Here my code :

  class ChooseYourCharacter extends React.Component {

      constructor(props) {
        super(props);
        this.state = {value: 'coconut'};

        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
      }

      handleChange(event) {
        this.setState({value: event.option});
      }

      handleSubmit(event) {
        alert('Your favorite flavor is: ' + this.state.value);
        event.preventDefault();
      }

      render() {
        return (
          <form onSubmit={this.handleSubmit}>
            <label>
              Pick your favorite La Croix flavor:
              <select multiple={true} value={this.state.value} onChange={this.handleChange}>
                <option value="grapefruit">Grapefruit</option>
                <option value="lime">Lime</option>
                <option value="coconut">Coconut</option>
                <option value="mango">Mango</option>
              </select>
            </label>
            <input type="submit" value="Submit" />
          </form>
        );
      }
    }
    ReactDOM.render(
             <ChooseYourCharacter/>,
             document.getElementById('root')
    )
4
  • 1
    See answer here: Retrieving value from <select> with multiple option in React
    – HollyOS
    Commented Apr 29, 2018 at 19:30
  • 1
    If you found the answer to your own question you can put it on an "answer" and accept it, for documenting purposes
    – SrThompson
    Commented Apr 30, 2018 at 20:23
  • Okay thank you guys, I will put it in the end of the regular delay
    – HoCo_
    Commented Apr 30, 2018 at 21:43
  • Thanks Holly Springsteen to sent me the link. I had already viewed it but an another view enlighten me.
    – HoCo_
    Commented May 1, 2018 at 20:27

5 Answers 5

13

Of my basic understanding, when you try to handle a Select form element in reactJS you generates an object in HTMLOptionsCollection.

The fundamental root to this object methods and properties is e.target.options.

Your items are stored in e.target.options.value property.

To access to a value stored in the options.value object, you can use the [i] loop value, hence e.target.options[i].value property.

The e.target.options[i].value return strings data types.

Following what I have just said, I assume the objects are stored respecting a number increasing convention as following :

e.target.options[i].value where { [i] : value, [i +1] : value (...)}...

By using e.target.options[i].selected you can control if there is a value stored at a specific location.

e.target.options[i].selected return you a boolean value, useful to handle the code flow.

It's up to you now.


Here my code to handle multiple select form in JSX with javascript code :

// Create the React Component


    class ChooseYourCharacter extends React.Component {

          // Set the constructor
          constructor(props) {
            super(props);
            this.state = {value: 'coconut'};

            // bind the functions
            this.handleChange = this.handleChange.bind(this);
            this.handleSubmit = this.handleSubmit.bind(this);
          }

          // extract the value to fluently setState the DOM
          handleChange (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.setState({value: value});
          }

          // display in client-side the values choosen
          handleSubmit() {
             alert("you have choose :" + this.state.value);

         }


    (...)
1
  • I dont see how this would work. handleChange is called each time an option is selected and overwrites the previous value of value. I just tried this out and can see exactly what I said happening.
    – ameyaraje
    Commented Jun 12, 2020 at 15:36
9

Currently learning React and I noticed this same code on the reactjs.org site. Below is my solution for handling multiple selected options.

  1. in the constructor, use an array for the initial value for 'value' in the state
  2. in the handleChange method, convert the event target's selectedOptions (HTMLOptionsCollection - array-like) to an array using Array.from(), and use a mapping function to get the value from each item

class ChooseYourCharacter extends React.Component {

      constructor(props) {
        super(props);
        //this.state = {value: 'coconut'};
        this.state = {value: ['coconut']};

        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
      }

      handleChange(event) {
        //this.setState({value: event.option});
        this.setState({value: Array.from(event.target.selectedOptions, (item) => item.value)});
      }

      handleSubmit(event) {
        alert('Your favorite flavor is: ' + this.state.value);
        event.preventDefault();
      }

      render() {
        return (
          <form onSubmit={this.handleSubmit}>
            <label>
              Pick your favorite La Croix flavor:
              <select multiple={true} value={this.state.value} onChange={this.handleChange}>
                <option value="grapefruit">Grapefruit</option>
                <option value="lime">Lime</option>
                <option value="coconut">Coconut</option>
                <option value="mango">Mango</option>
              </select>
            </label>
            <input type="submit" value="Submit" />
          </form>
        );
      }
    }
    ReactDOM.render(
             <ChooseYourCharacter/>,
             document.getElementById('root')
    )
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

9

Here is how to get the options selected by the user using a functional component and the useState hook rather than a class component:

import React, { useState } from "react";

const ChooseYourCharacter = function(props) {
    const [selectedFlavors, setSelectedFlavors] = useState([]);

    const handleSelect = function(selectedItems) {
        const flavors = [];
        for (let i=0; i<selectedItems.length; i++) {
            flavors.push(selectedItems[i].value);
        }
        setSelectedFlavors(flavors);
    }

    return (
        <form>
            <select multiple={true} value={selectedFlavors} onChange={(e)=> {handleSelect(e.target.selectedOptions)}}>
                <option value="grapefruit">Grapefruit</option>
                <option value="lime">Lime</option>
                <option value="coconut">Coconut</option>
                <option value="mango">Mango</option>
            </select>
        </form>
    );
};

export default ChooseYourCharacter;
1

As you are using multi-select you should declare your state variable as an array

  constructor(props) {
    super(props);
    this.state = {value: []};//This should be an array

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

I have created a blog for reactjs form posting with multi select control. You may go here for more details https://handyopinion.com/git-commands-cheat-sheet/

0

I am using react bootstrap 4 here

   <Form.Group >
          <Form.Label>Form Label</Form.Label>
          <Form.Control
            as="select"
            multiple
            // value={formCatState}
            onChange={(event) => {
              let target = event.target as HTMLSelectElement
              console.log(target.selectedOptions);
            }}
          >
            <option>example cat 1</option>
            <option>Example cat 2</option>
            <option>Example cat 3</option>
            <option>Example cat 4</option>
          </Form.Control>
            <Form.Text muted> hold ctrl or command for multiple select</Form.Text>
        </Form.Group>

Not the answer you're looking for? Browse other questions tagged or ask your own question.