1

I'm using a Vuejs 1.0 directive to turn a select field (single and multiple) into a Select2 jQuery plugin field.

Vue.directive('select2', {
    twoWay: true,
    priority: 1000,

    params: ['max-items'],

    bind: function () {
        var self = this;
        console.log(self.params);

        $(this.el)
            .select2({
                maximumSelectionLength: self.params.maxItems,
                theme: 'bootstrap',
                closeOnSelect: true
            })
            .on('change', function () {
                var i, len, option, ref, values;
                if (self.el.hasAttribute('multiple')) {
                    values = [];
                    ref = self.el.selectedOptions;
                    for (i = 0, len = ref.length; i < len; i++) {
                        option = ref[i];
                        values.push(option.value);
                    }
                    return self.set(values);
                } else {
                    return self.set(self.el.value);
                }
            })
    },
    update: function (value, oldValue) {
        $(this.el).val(value).trigger('change')
    },
    unbind: function () {
        $(this.el).off().select2('destroy')
    }
});

This all works fine. I'm also trying to bind a model to the value of the field but can't seem to get it to bind properly.

<select class="form-control" name="genre" v-model="upload.genre" v-select2="">
<option value="50">Abstract</option>
<option value="159">Acapella</option>
<option value="80">Acid</option>
...
</select>

The upload.genre property does not update automatically.

1 Answer 1

3

v-model is actually syntactic sugar on passing a prop and on change event setting the value, so following:

<input v-model="something">

is equivalent of

<input v-bind:value="something" v-on:input="something = $event.target.value">

You have to also make similar changes, You can see this type code in the select2 example provided by vue team.

  .on('change', function () {
    vm.$emit('input', this.value)
  })

With Vue 1.0

As you are using vue 1.0, there is a two-way options for directives which helps to write data back to the Vue instance, you need to pass in twoWay: true. This option allows the use of this.set(value) inside the directive:

Vue.directive('select2', {
  twoWay: true,
  bind: function () {
    this.handler = function () {
      // set data back to the vm.
      // If the directive is bound as v-select2="upload.genre",
      // this will attempt to set `vm.upload.genre` with the
      // given value.
      this.set(this.el.value)
    }.bind(this)
    this.el.addEventListener('input', this.handler)
  },
  unbind: function () {
    this.el.removeEventListener('input', this.handler)
  }
})

and in HTML:

<select class="form-control" name="genre" v-select2="upload.genre">
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the answer. I neglected to mention that I'm using Vuejs 1.0 and I'm also using a directive not a component. Can it still be done?
Thanks for the answer. If you could kindly help me once again. I've used your code and it works great when a model is provided, but it doesn't work if no model is provided and the select list already has a selected item. It always uses the models value to set the select2 list value - here's the fiddle - jsfiddle.net/4r36a1s1 - appreciate the help.
@Wasim You have to give the initial value in update inside your directive, see this fiddle, I have hardcode this as of now, it can be passed as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.