16

I have a VueJS instance with some data :

var vm = new Vue({
    el: '#root',
    data: {
        id: '',
        name: {
            firstname: "", 
            lastname: "", 
            country: "", 
            valueset: false
        },
// ...

In my HTML, I also have :

<input class="id" type="text" size="4" maxlength="4" v-model.lazy="id" v-on:change="create_casenr">

Therefore after filling up this field, the method create_casenr of my instance is triggered.

create_casenr: function(event) {
    // update the full name of user
    $.ajax({
        url: 'http://elk.example.com:9200/users/user/' + this.id
    })
    .done(function(data) {
        console.log(data);
        this.name = data._source;
        this.name.valueset = true;
        console.log(this.name);
    })
// ...

What happens is that :

  • create_casenr is called upon the change in the field (OK)
  • the AJAX call goes through successfully, I see the expected output on the console for both dataand this.name (OK)
  • but name is not updated in the instance of VueJS.

I can see it is not updated because other parts of my code which rely on it do not see it; I also checked with the VueJS Chrome add-on and all the variables are correctly set (including id), except for name.

Is there a specific way I should address the data of a VueJS instance when modified via a jQuery AJAX call?

3 Answers 3

20

You have a scope issue of this.name in your AJAX success handler.

The this.name inside is not the same as this.name in your Vue component. So your name is not getting set in the Vue component.

You may use arrow functions to get around this issue:

$.ajax({
    url: 'http://elk.example.com:9200/users/user/' + this.id
    }).done(data => {
        this.name = data._source;  // 'this' points to outside scope
        this.name.valueset = true;
    });

Similar answer: https://stackoverflow.com/a/40200989/654825

More info on Arrow functions: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

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

3 Comments

For future readers: the arrow function is not supported by IE as of October 2016 (and probably will never be as IE 11 is the last IE). Edge, Chrome, Firefox do work.
Yes, IE11 does not support arrow functions. But when use vue-cli to make a production build, babel compiler takes care of converting arrow functions to ES5 compatible code. So you can still use arrow functions, but do the entire development in Chrome / Firefox, and final testing in IE11.
Thank you - I did not know about vue-cli.
10

not same scope for this.name

create_casenr: function(event) {
// update the full name of user
$.ajax({
    url: 'http://elk.example.com:9200/users/user/' + this.id
})
.done(function(data) {
    console.log(data);
    this.name = data._source;
    this.name.valueset = true;
    console.log(this.name);
}.bind(this))

add a bind(this)

2 Comments

It looks like .bind() is deprecated in jQuery 3 and discouraged earlier (according to api.jquery.com/bind)
@WoJ : it's bind ES5.1 function to bind internal this of anonymous function, see here : developer.mozilla.org/fr/docs/Web/JavaScript/Reference/… and it's not deprecated ;-)
0

Another thing that plays a role here is how Vue.js updates the DOM. For details read this section in the documentation: Async Update Queue

In short use "nexTick" callback to process your code after Vue.js is done updating the DOM.

methods: {
   someMethod() {
      var self = this;
      $.ajax({
        url: 'http://...',
      }).done(function (data) {
        self.a = data.a;
        self.b = data.b;
        self.$nextTick(function () {
           // a and b are now updated
        }
      });
   }
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.