Svedr Svedr - 3 months ago 23
Javascript Question

Set object in data from a method in VUE.js

I have been stuck with this issues for 2 hours now and I really can't seem to get it work.



const app = new Vue({
el: '#book-search',
data: {
searchInput: 'a',
books: {},
},
methods: {
foo: function () {
axios.get('https://www.googleapis.com/books/v1/volumes', {
params: {
q: this.searchInput
}
})
.then(function (response) {
var items = response.data.items
for (i = 0; i < items.length; i++) {

var item = items[i].volumeInfo;

Vue.set(this.books[i], 'title', item.title);

}
})
.catch(function (error) {
console.log(error);
});

}
}
});





When I initiate search and the API call I want the values to be passed to data so the final structure looks similar to the one below.

data: {
searchInput: '',
books: {
"0": {
title: "Book 1"
},
"1": {
title: "Book 2"
}
},


Currently I get
Cannot read property '0' of undefined
.

Answer Source

Problem lies here:

Vue.set(this.books[i], 'title', item.title);

You are inside the callback context and the value of this is not the Vue object as you might expect it to be. One way to solve this is to save the value of this beforehand and use it in the callback function.

Also instead of using Vue.set(), try updating the books object directly.

const app = new Vue({
  el: '#book-search',
  data: {
    searchInput: 'a',
    books: {},
  },
  methods: {
    foo: function () {
      var self = this;
      //--^^^^^^^^^^^^ Save this
      axios.get('https://www.googleapis.com/books/v1/volumes', {
        params: {
          q: self.searchInput
          //-^^^^--- use self instead of this
        }
      })
      .then(function (response) {
        var items = response.data.items
        var books = {};
        for (i = 0; i < items.length; i++) {

          var item = items[i].volumeInfo;
          books[i] = { 'title' : item.title };
        }
        self.books = books;
      })
      .catch(function (error) {
        console.log(error);
      });

    }
  }
});

Or if you want to use Vue.set() then use this:

Vue.set(self.books, i, {
     'title': item.title
});

Hope this helps.