Binding select2 to Vue js model data

I am using select2 to enhance the select html element. I want to bind the value of the select element to a Vue variable, however Select2 seems to prevent this.

What is the best way to achieve this data binding and listen for events while maintaining Select2 behavior. I assume this is a case of binding select2 events to a Vue instance.

I made a fiddle demonstrating the problem (doesn't work below, but works on jsfiddle):

$('#things').select2(); new Vue({ el: "#vue-example", data: { thing: null, thing2: null }, methods: { log: function(str) { $('#log').append(str + "<br>"); } } }); 
 select { width: 50%; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script> <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/0.12.8/vue.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script> <div id="vue-example"> <label>Select2 Select Box</label> <select name="things" id="things" v-model="thing" v-on="change: log('you changed thing1')"> <option value="1">One</option> <option value="2">Two</option> <option value="3">Three</option> <option value="4">Four</option> <option value="5">Five</option> </select> <br> <br> <label>Native Select Box</label> <select name="things" id="things" v-model="thing2" v-on="change: log('you changed thing2')"> <option value="1">One</option> <option value="2">Two</option> <option value="3">Three</option> <option value="4">Four</option> <option value="5">Five</option> </select> <pre>{{ $data | json }}</pre> <div id="log"> </div> </div> 
+5
source share
4 answers

The quick answer is correct. You just need to define and update this code to reflect the differences in Select2.

http://jsfiddle.net/qfy6s9Lj/10/

 Vue.directive('selecttwo', { twoWay: true, bind: function () { $(this.el).select2() .on("select2:select", function(e) { this.set($(this.el).val()); }.bind(this)); }, update: function(nv, ov) { $(this.el).trigger("change"); } }); new Vue({ el: "#vue-example", data: { thing: null, thing2: null }, methods: { log: function(str) { $('#log').append(str + "<br>"); } } }); 
 select { width: 50%; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script> <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/0.12.8/vue.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script> <div id="vue-example"> <label>Select2 Select Box</label> <select name="things" id="things" v-model="thing" v-selecttwo="thing" v-on="change: log('you changed thing1')"> <option value="1">One</option> <option value="2">Two</option> <option value="3">Three</option> <option value="4">Four</option> <option value="5">Five</option> </select> <br> <br> <label>Native Select Box</label> <select name="things" id="things" v-model="thing2" v-selecttwo="thing2" v-on="change: log('you changed thing2')"> <option value="1">One</option> <option value="2">Two</option> <option value="3">Three</option> <option value="4">Four</option> <option value="5">Five</option> </select> <pre>{{ $data | json }}</pre> <div id="log"> </div> </div> 
+8
source

Shorter solution:

 Vue.directive('select2', { inserted(el) { $(el).on('select2:select', () => { const event = new Event('change', { bubbles: true, cancelable: true }); el.dispatchEvent(event); }); $(el).on('select2:unselect', () => { const event = new Event('change', {bubbles: true, cancelable: true}) el.dispatchEvent(event) }) }, }); 

Trae's answer is good, but the value is already stored in the select element, so all you have to do is send an event so that Vue knows that we changed it.

Just do:

 <select v-model="myprop" v-select2> ... 
+4
source

This solution works for the Chosen plugin, but you can do the same with Select2 to make it work:

http://jsfiddle.net/simplesmiler/qfy6s9Lj/8/

 Vue.directive('chosen', { twoWay: true, // note the two-way binding bind: function () { $(this.el) .chosen({ inherit_select_classes: true, width: '30%', disable_search_threshold: 999 }) .change(function(ev) { // two-way set this.set(this.el.value); }.bind(this)); }, update: function(nv, ov) { // note that we have to notify chosen about update $(this.el).trigger("chosen:updated"); } }); var vm = new Vue({ data: { city: 'Toronto', cities: [{text: 'Toronto', value: 'Toronto'}, {text: 'Orleans', value: 'Orleans'}] } }).$mount("#search-results"); 
+2
source

I made a plugin for select2 a few days ago.

https://github.com/halupi/vue-select2

Hope this helps!

0
source

All Articles