Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

vue.js select2 multiple select

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
         },
like image 437
fido Avatar asked May 12 '17 15:05

fido


2 Answers

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.

like image 134
Bert Avatar answered Sep 22 '22 18:09

Bert


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());
});
like image 30
aleixfabra Avatar answered Sep 19 '22 18:09

aleixfabra