How to use Select2 with Reactjs?
Asked Answered
D

5

17

I have dependent fields like this

    <List>
     <select>
      <option></option>
      <option></option>
     </select>
     <select>
      <option></option>
      <option></option>
     </select>
     <input />
   </List>

If I had 5 <List/> components.How do I add Select2 to each component.I googled online.But couldn't find any working solution.

Code below for react-select.Getting error TypeError: event.target is undefined.

var React = require('react');
var ReactDOM = require('react-dom');
var Select = require('react-select');

var Page = React.createClass({

    getInitialState: function () {
        return {
            firstValue: ''
        }
    },

    handleFirstLevelChange : function (event) {
        this.setState({
            firstValue: event.target.value
        });
    },
    render : function(){

        var options = [
            { value: '', label: 'Select an option' },
            { value: 'one', label: 'One' },
            { value: 'two', label: 'Two' }
        ];

        return (<Select
            value={this.state.firstValue}
            options={options}
            onChange={this.handleFirstLevelChange}
            />)
    }
});

ReactDOM.render(<Page />, document.getElementById('root'));
Diageotropism answered 3/2, 2016 at 11:56 Comment(2)
I tried adding select2 in the html page and used this snippet.But It changed only the first select element.The dependent select fields were unchanged. <script type="text/javascript"> $('select').select2(); </script>Diageotropism
This is useful for wrapping jQuery libs in React, in general: github.com/ryanflorence/react-training/blob/gh-pages/lessons/…Trihedron
G
19

We are using this wrapper, but there are too many problems around it.

First of all, you can't test code where it is used in NodeJS, because of this issue. Secondly we had problems with initialization of various select2 components via defaultValue parameter. Only one (randomly) of these elements was initalized.

Therefore we going to dump it and replace with react-select soon.

EDIT: We replaced react-select2-wrapper with react-select. It works great for us.

Ghirlandaio answered 3/2, 2016 at 20:10 Comment(10)
even react-select has issues.I can't set the state.If I try to set the state the dropdown doesn't close.Diageotropism
Hmm not sure. We didn't try it so far. It suppose to be very configurable. Isn't there some flag in docs?Ghirlandaio
<Select value={this.state.firstValue} options={options} onChange={this.handleFirstLevelChange} /> handleFirstLevelChange : function (event) { this.setState({ firstValue: event.target.value }); } I get TypeError: event.target is undefinedDiageotropism
getting an error TypeError: event.target is undefinedDiageotropism
added detail to my question.I dont know why I get the TypeError: event.target is undefined errorDiageotropism
It seems to me that handleFirstLevelChange should be bound to this: this.handleFirstLevelChange.bind(this).Ghirlandaio
I was also having an issue with defaultValue and it turns out that it's supposed to be sent in as an attribute of Select2 rather than an option (i.e. <Select2 defaultValue={value} options={select2opts} />Garofalo
I recommend switching to react-select. Not a single problem with that library.Ghirlandaio
@luboskrnac: react-select might be good but not perfect. One of the biggest problem I see with that package is that you have no support for optgroups . Plus, the idea of delegating an onchange event to every control being mandory for the value to actually change in the dropdown is something i believe is not very friendly in terms of performance.Rigby
"Not a single problem"? 1,202 open issues at github.com/JedWatson/react-select/issues I've had nothing but problems.Antony
B
12

If you're using refs [docs], you can access the node via its refs attribute in the componentDidMount function and pass that to select2() :

var Select = React.createClass({
  handleChange: function () {
    this.prop.onChange(
      this.refs.myRef.value
    );
  },

  componentDidMount: function () {
    // Call select2 on your node
    var self = this;
    var node = this.refs.myRef; // or this.refs['myRef']
    $(node)
      .select2({...})
      .on('change', function() {
        // this ensures the change via select2 triggers 
        // the state change for your component 
        self.handleChange();
      });
  },

  render: function () {
    return (
      <select 
        ref="myRef"
        onChange={this.handleChange}>
        // {options}
      </select>
    );
  }
});

I don't believe this is the "React way," but this may help if you don't want to use react-select or some other tool.

Billbillabong answered 22/6, 2016 at 17:49 Comment(0)
T
9

Since you're using React, you'd be better off looking for React components rather than jQuery plugins. You can use for eaxmple react-select, which is pretty similar to Select2.

Trihedron answered 3/2, 2016 at 12:16 Comment(5)
But I need a solution for Select2 because I am currently using it my application.Diageotropism
@Vishwasraj did you get the solution im breaking my head for this :(Irksome
@Vikram no solution found.changed to materialize css library.link to libraryDiageotropism
@Vishwasraj shit it will be so difficult to any other developer taking over this project becoz the rest of the modules are written on JQueryIrksome
@Vikram yes...rewriting select2 library from stratch to make it work for react framework is the only possible solution.Diageotropism
T
1

Simple wrapper.

Add select2 js + css on index.html, write wrapper over select input

function renderOptions(option_items) {
    if(option_items) {
        return Object.entries(option_items).map(function (item) {
            return <option key={item[0]} value={item[0]}>{item[1]}</option>
        })
    }
}

class Select2Input extends Component {

    constructor(props) {
        super(props)
        this.ref_input = React.createRef()
    }

    /**
    * Add select2 bind and send onChange manually
    */
    componentDidMount() {
        const self = this

        $(self.ref_input.current).select2({
            tags: true,
        }).on('change', function(event) {
            var value = $(event.currentTarget).val()
            if(self.props.multiple === true) {
                value = List(value)
            }
            self.props.onChange(self.props.name, value)
        })
    }

    /**
    * Emit change event for reload select2 if options has change
    */
    componentDidUpdate(prevProps) {
        if(prevProps.option_items !== this.props.option_items) {
            $(this.ref_input.current).change()
        }
    }

    render() {
        return <select className="form-control"
                    multiple={this.props.multiple}
                    name={this.props.name}
                    value={this.props.value}
                    disabled={this.props.disabled}
                    ref={this.ref_input}>
                            {renderOptions(this.props.option_items)}
            </select>
    }
}
Tusker answered 7/6, 2019 at 7:35 Comment(0)
I
0

If you are just using jquery and select2 in a react application, you can simply link the cdn for Jquery and select2 in public/index.html inside "head" tag. Then in your src/components/component.js. You can use jquery select2 like this:

constructor(props) {
        super(props);
        this.state = {
            Provinces: [],
        };
        this.select2PX = this.select2PX.bind(this);
        // this.ApiTest = this.ApiTest.bind(this);
}

select2PX(){
        window.$(document).ready(function() {
            window.$('#phuong-xa').select2();
        });
}

componentDidMount(){
  this.select2PX();
}


render(){
   return (.... html);
}

Because you use the cdns in the public/.html file, you need to use window.$ to use jquery. It achieves the same thing as using select2 in a html file.

Ils answered 15/10, 2018 at 7:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.