Select2 on change event is not working in Vuejs
Solution 1
To get this to work with a directive, we need to understand how v-model
works. From the docs:
<input v-model="something">
is just syntactic sugar for:
<input v-bind:value="something" v-on:input="something = $event.target.value">
In the case of a select element, v-model
will listen for the change
event (not input
). So, if the directive dispatches a change
event when the element changes, then v-model
will work as expected.
Here is an updated version of your code (works in Vue 2):
Vue.directive('select', {
twoWay: true,
bind: function (el, binding, vnode) {
$(el).select2().on("select2:select", (e) => {
// v-model looks for
// - an event named "change"
// - a value with property path "$event.target.value"
el.dispatchEvent(new Event('change', { target: e.target }));
});
},
componentUpdated: function(el, me) {
// update the selection if the value is changed externally
$(el).trigger("change");
}
});
var app = new Vue({
el: '#app',
data: {
supplier_id: "niklesh"
},
})
$('#supplier_id').select2({});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.4/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/css/bootstrap.css">
<div id="app">
{{ supplier_id }}
<select id="supplier_id" class='form-control' v-model='supplier_id' v-select='supplier_id'>
<option value="atul">Atul</option>
<option value="niklesh">Niklesh</option>
<option value="sachin">Sachin</option>
</select>
</div>
And here's a version that works in Vue 3 (custom directives have different syntax, linked here):
var app = Vue.createApp({
data: function() {
return {
supplier_id: "niklesh"
}
}
})
app.directive('select', {
beforeMount: function (el, binding, vnode) {
$(el).select2().on("select2:select", (e) => {
// v-model looks for
// - an event named "change"
// - a value with property path "$event.target.value"
el.dispatchEvent(new Event('change', { target: e.target }));
});
},
updated: function(el) {
// update the selection if the value is changed externally
$(el).trigger("change");
}
});
app.mount('#app');
$('#supplier_id').select2({});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
<script src="https://unpkg.com/[email protected]"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/css/bootstrap.css">
<div id="app">
{{ supplier_id }}
<select id="supplier_id" class='form-control' v-model='supplier_id' v-select='supplier_id'>
<option value="atul">Atul</option>
<option value="niklesh">Niklesh</option>
<option value="sachin">Sachin</option>
</select>
</div>
Solution 2
By assigning select2 value to vuejs data I am able to fix this problem. I didn't use custom directive here.
var app = new Vue({
el: '#app',
data: {
supplier_id: "niklesh"
},
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
});
$('#supplier_id').on("change",function(){
app.supplier_id = $(this).val();
console.log('Name : '+$(this).val());
});
$('#supplier_id').select2({});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.4/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/css/bootstrap.css">
<div id="app">
Name : {{ supplier_id | capitalize }}
<select id="supplier_id" class='form-control' v-model='supplier_id'>
<option value="atul">Atul</option>
<option value="niklesh">Niklesh</option>
<option value="sachin">Sachin</option>
</select>
</div>
Please comment if this is not good way or any better solution you suggest.
Solution 3
<select v-model="selected">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
const self = this;
$("select").change(function () {
const val = $(this).find("option:selected").val();
self.selected = val;
});
Niklesh Raut
Jo pass hai wahi khaas hai, Baki sab bakwaas hai. ✍(◔◡◔) : rishiraut16 AT gmail.com
Updated on June 05, 2022Comments
-
Niklesh Raut almost 2 years
I was working with select2 in vuejs , I found vuejs is not working with jquery select2 as vuejs is working with navite html.
I am using this code
Vue.directive('select', { 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"); } }); var app = new Vue({ el: '#app', data: { supplier_id: "niklesh" } }) $('#supplier_id').select2({});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.4/vue.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/css/bootstrap.css"> <div id="app"> {{ supplier_id }} <select id="supplier_id" class='form-control' v-model='supplier_id' v-select='supplier_id'> <option value="atul">Atul</option> <option value="niklesh">Niklesh</option> <option value="sachin">Sachin</option> </select> </div>
Please share your reply to handle this problem.
-
darryn.ten over 7 yearsasked AND answered 1 minute ago?
-
Niklesh Raut over 7 years@darryn.ten: This is my own answer, although its works through jquery but I would be great if I can solve this through vuejs.
-
asemahle over 7 years@Rishi: I don't think this is a bad solution, but your original idea of using a directive seems more reusable. I've added a solution showing how you could use a directive instead.
-
KevinO over 5 yearsThis answer would be improved by providing an explanation as to why it works, and why it is a better approach than the accepted answer.
-
Patrizio Bekerle over 5 yearsThank you for your solution! I am using a multi-select, so I also had to trigger the change event on
select2:unselect
, like this:$(el).select2().on("select2:select select2:unselect", (e) => {
-
Moauya Meghari over 3 yearsThe easiest and simplest solution. Thanks.
-
e4rthdog almost 3 yearsThis doen't seem to work with Vue3. Any ideas why?
-
asemahle almost 3 years@e4rthdog Directives work differently in Vue 3. I added a code snippet for Vue 3.