user3673959
user3673959

Reputation:

How to use Select2 with Reactjs?

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

Upvotes: 17

Views: 55029

Answers (6)

Sandeep Jain
Sandeep Jain

Reputation: 1261

    import Select2 from "react-select";

//initialization    
options: [
            {
              label: "",
              value: "",
            },
          ];

          //setting options value of drop down
            this.state.options.push({
              label: val.label,
              value: val.id,
            });

  // Added search filterOption
   customFilter = (option, searchText) => {
    if (
      option.data.label.toLowerCase().includes(searchText.toLowerCase()) ||
      option.data.value.toLowerCase().includes(searchText.toLowerCase())
    ) {
      return true;
    } else {
      return false;
    }
  };          

   
                              Label Name{" "}
                              <Select2
                                        id="selectId"
                                        className="reactSelect"
                                        name={this.state.selectedDisplay}
                                         value={this.state.selectedDisplay}
                                         placeholder={"Type to search..."}
                                         onChange={(e) =>
                                           this.setState({
                                             selected:e.value,
                                               selectedDisplay:e,
                                           })
                                         }
                                        options={this.state.options}
                                        filterOption={this.customFilter}
                                        >
                                

Upvotes: 0

dibrovsd
dibrovsd

Reputation: 89

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

Upvotes: 1

ThomasH.Allen
ThomasH.Allen

Reputation: 123

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.

Upvotes: 0

luboskrnac
luboskrnac

Reputation: 24581

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.

Upvotes: 19

aboutaaron
aboutaaron

Reputation: 5389

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.

Upvotes: 12

mik01aj
mik01aj

Reputation: 12402

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.

Upvotes: 8

Related Questions