2

I have tried to create a vuejs2 directive, which would pick the already rendered select and wrap it into select2. This part is working but doesn't pick the selected value:

Vue.directive('select', {
    inserted: function (el) {

        $(el).select2({
            matcher: modelMatcher,
            minimumResultsForSearch: 6,
            dropdownAutoWidth: true,
            width: 'auto'
        });

    }
});

Any ideas how to do this? This probably worked with vuejs 1:

https://gist.github.com/themsaid/c0548e19f247b832ac4f

but not working any more.

1 Answer 1

1

The issue is select2, when changed, throws a jQuery.Event Object, and Vue only reacts to regular JavaScript events.

So the solution is to, after initializing select2, listen to the change jQuery.Event it emits and emit a change CustomEvent as well, so Vue picks it up.

When Vue picks the change CustomEvent, it will update the v-model.

Demo below.

Vue.directive('select', {
  inserted: function(el) {
    var self = this;
    $(el).select2({
      //matcher: modelMatcher,
      //minimumResultsForSearch: 6,
      //dropdownAutoWidth: true,
      width: 'auto'
    }).on('change', function(e) {
      if (e.detail === "vue-directive") {
        return; // prevent stack overflow (i.e. listening to the event we threw ourselves)
      }
      // throw regular change (non jQuery) event, so vue reacts
      el.dispatchEvent(new CustomEvent("change", {
        detail: "vue-directive"
      }));
      return false;
    })
  }
});
new Vue({
  el: '#app',
  data: {
    states: ["AL", "AK", "AZ"],
    selectedState: "AK",
  }
})
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <select v-model="selectedState" v-select>
    <option v-for="state in states" :value="state">{{ state }}</option>
  </select>
  <p>Selected State: {{ selectedState }}</p>
</div>

Note that's just one way of doing it, there's a great variety of possibilities, making use of Vue's Custom Directives Hook Functions. Also note that the example I show above is sligthly simpler than the gist you provided, as it does not handle the unbind hook, for instance. The implementation should be straightforward, OTOH.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! What I was trying to achieve was more like this: jsfiddle.net/mg4zr2Ly/4 But your answer helped me to accomplish it.

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.