Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vuejs binding not working if update by jquery

Jsfiddle

HTML:

<div id="testVue">

<input id="test" v-model="testModel"/>

<button @click="clickMe()">Click me</button>

<button @click="showValue()">Show value</button>

</div>

Javascript

var testVue = new Vue({
  el: '#testVue',

  data: {
    testModel: 'Hello Vue!'
  },

  methods: {

    clickMe: function() {
        $("#test").val("testing");
        console.log(this.testModel);
    },

    showValue: function() {
        console.log(this.testModel);
    }
  }
});

I totally understand I shouldn't do this in Vuejs $("#test").val("testing");, I should have do like this.testModel="testing";

But I can't understand why this basic binding doesn't work in Vuejs? I have quite a lot of HTML component that update the input box via jquery, for example Calendar, Autocomplete and Select2, all will update the Input box via non-vuejs way.

Any easy way to handle this?

like image 201
Sam YC Avatar asked Oct 26 '17 13:10

Sam YC


2 Answers

its too late to answer but for anyone stumbles on this in future can use my suggestion to work with .

I had read somewhere that This is a jQuery problem, trigger/val() doesn't dispatch native events in some cases. So we will dispatch native JS Event after changing values with jQuery val()

$("#test").val("testing")[0].dispatchEvent(new Event('input'))

Points to note :-

  • in Vue, text and textarea elements use input event and checkboxes, radio and select uses change as an event. So dispatchEvent accordingly;
  • i assume that using id selector $("#test") you are applying this to single dom element thats why i have choosed [0] th element. if you are intending it to multiple elements then you can use for loop to dispatchEvent on al.

reference :- Vue Issues on Github

like image 56
santoshe61 Avatar answered Sep 19 '22 05:09

santoshe61


Best way is to let jQuery change the data instead of the input val to keep everything synced.

Like this:

let mainState = { inputVal: 'testing' };

let app = new Vue({
  el: '#app',
  data: mainState,
  methods: {
    vueThing() {
      this.inputVal = 'Vue value';
    }
  }
}); 

$('#jqThing').on('click', function() {
  mainState.inputVal = 'jQuery Value';
});

https://jsfiddle.net/6evc921f/

Or wrap the jQuery elements constructors in Vue components and just use them in Vue enhanced pages

like image 27
NxWebster Avatar answered Sep 19 '22 05:09

NxWebster