vue.js select2 multiple select

10,468

Solution 1

It looks like you used the Vue documentation example of a wrapper for select2 as your base. I've modified the wrapper to handle a multiple select here.

I expect the main issue you were running into is that if you do this:

self.$emit('input',  $(this).val()) // multiple select

You will end up in an infinite loop, because you are emitting a new array, which is going to trigger the watch,

value: function (value) {
    $(this.$el).val(value).trigger('change');
},

which triggers the change, which triggers the watch, etc.

To fix that, just check to see if the value passed into the watch is identical to the values of the select, and if it is, ignore it. Here's how I did that.

value: function (value) {
  // check to see if the arrays contain the same values
  if ([...value].sort().join(",") !== [...$(this.$el).val()].sort().join(","))
    $(this.$el).val(value).trigger('change');
},

Notice also that I turned this into it's own component, select2Multiple. You might want to have one component that handles multiple selected values and another for single values.

Solution 2

As I answered here: Using Select2 (multiple selections) with vue.js

Change this:

.on('change', function () {
  self.$emit('input', this.value); // Don't use this.value
});

To this:

.on('change', function () {
  self.$emit('input', $(this).val());
});
Share:
10,468
fido
Author by

fido

Updated on July 07, 2022

Comments

  • fido
    fido almost 2 years

    For many days I've searched to find an answer to this error. I tried many alternatives but nothing worked.

    I need to select multiple values. When I select multiple values, my code hangs, but when I use a single select it works well with self.$emit('input', this.value). What I need is to select multiple values.

    Select2.vue

    <template>
        <select multiple class="input-sm" :name="name">
            <slot></slot>
        </select>
    </template>
    <style src="select2/dist/css/select2.min.css"></style>
    <style src="select2-bootstrap-theme/dist/select2-bootstrap.min.css"></style>
    
    <script>
        import Select2 from 'select2';
    
        export default{
            twoWay: true,
            priority: 1000,
            props: ['options', 'value', 'name'],
            data(){
                return{
                    msg: 'hello'
                }
            },
            mounted(){
                var self = this;
                $(this.$el)
                    .select2({theme: "bootstrap", data: this.options})
                    .val(this.value)
                    .trigger('change')
                    .on('change', function () {
                        //self.$emit('input', this.value) //single select worked good
                        self.$emit('input',  $(this).val()) // multiple select
                    })
            },
            watch: {
                value: function (value) {
                    $(this.$el).val(value).trigger('change');
                },
                options: function (options) {
                    $(this.$el).select2({ data: options })
                }
            },
            destroyed: function () {
                $(this.$el).off().select2('destroy')
            }
        }
    </script>
    

    new.vue

        <p>Selected: {{ model.users_id }}</p>
                  <select2 :options="options" v-model="model.users_id" name="options[]" style="width: 1000px; height: 1em;" class="form-control">
               <option value="0">default</option>
                </select2>
    
        export default {
                data(){
                    return {
                        model: {
                            'users_id': [],
                        },
                        options: [],
    
    components:{
                'select2': Select2
             },