Mitchel Jager
Mitchel Jager

Reputation: 445

Updated list when var (array) changes

I have a list of items, which I want to update when I update the array. This is my list of items:

<li v-for="page in pages" class="menu__item">
    <a class="menu__link" @click="currentPage = page.id">{{ page.title }}</a>
</li>

I have a variable which is an array:

data: {
    pages: [],
    menuVisible: false
},

I have a watch set up which updates the variable when required:

watch: {
  'menuVisible': function(val, oldVal) {
    $.getJSON('/pages/json/list.json', function(json){
      this.pages = json;
    });
  }
}

When "menuVisible" updates, it fires this, and the var changes, but the list does not.

To give a basic idea of what I am trying to achieve; I have a list of pages. A new page is created via a ajax submit. When the user opens the menu with the list of pages, it updates menuVisible, which in turn updates the variable. I want it to update the list of pages, but it does not.

What am I missing?

Upvotes: 0

Views: 179

Answers (2)

craig_h
craig_h

Reputation: 32734

I think this is just a scope issue, this.pages is inside an anonomous function where the context of this is the function itself, not the Vue instance. To avoid this you can either use an arrow function if you are able to us ES6 (it does require something like babel to compile for use in a browser):

watch: {
  'menuVisible': function(val, oldVal) {
    $.getJSON('/pages/json/list.json', (json) => {
      this.pages = json;
    });
  }
}

Or you just need to set a variable pointing to this outside the ajax request:

watch: {
  'menuVisible': function(val, oldVal) {
    var self = this; // set self to 'this'

    $.getJSON('/pages/json/list.json', function(json){
      self.pages = json;
    });
  }
}

Upvotes: 1

Mani Jagadeesan
Mani Jagadeesan

Reputation: 24275

You have an issue with the binding of this in your JSON response handler.

this.pages inside function(json) {..} is not the same as this.pages of Vue component. function() {..} creates a separate context inside the curly braces. Therefore, your pages array is not getting updated.

You can also verify the above using Vue-devtools

To resolve this bug, please change your watch function as follows:

watch: {
  'menuVisible': function(val, oldVal) {
    $.getJSON('/pages/json/list.json', json => {
      this.pages = json;
    });
  }
}

In line 3 of the above function, you can notice that now it uses something called arrow function. The arrow function syntax ensures that your this in the outerscope (Vue component) is the same as the this of your JSON response handler function.

Alternatively you may also do var that = this outside json response handler, and set that.pages inside the JSON response handler. Ref: What does 'var that = this;' mean in JavaScript?

Upvotes: 0

Related Questions