dangchithao
dangchithao

Reputation: 633

VueJS does not update DOM after fetch data from API?

I am trying to create an example about the list of photos and I see a trouble when binding data to the component after call API.

JS code:

<script>
// photo item
Vue.component('photo-item', {
   props: ['photo'],
   template: `<li>{{ photo.name }}</li>`
});

// List of photos
Vue.component('photo-list', {
   props: ['photos'],

   template: `
   <ul id="photo-list">
      <photo-item v-for="photo in photos" :photo="photo"></photo-item>
   </ul>`
});

new Vue({
   el: "#photo_detail",
   data: {
      photos: []
   },

   created: function() {
      axios
       .get('/api/photos')
       .then(function (response) {
           this.photos = response.data; // Data existed
       })
       .catch(function (err) {
           console.log(err);
       });
   }
 })
 </script>

HTML code

<main id="photo_detail">
    <photo-list v-for="photo in photos" :photo="photo"></photo-list>
</main>

After fetching all photos from API and as my understand then the variable photos will auto binding and VueJS will update DOM.

VueJs 2.1.6

Any help.

Thanks!

Upvotes: 4

Views: 12141

Answers (2)

Max Martynov
Max Martynov

Reputation: 739

Your code is not correct.

Problems:

  1. It will be better to define used components for each component, like components: {photoItem}.
  2. In your axios callback you use function and that means, that you use wrong context inside (this.photos). Use arrow function (() => {}) instead of the function () {}
  3. The directive v-for requires directive :key=""

I've fixed it below.

// photo item
const photoItem = Vue.component('photo-item', {
   props: ['photo'],
   template: `<li>{{ photo.name }}</li>`
});

// List of photos
const photoList = Vue.component('photo-list', {

  // define used components
  components: {photoItem},
  props: ['photos'],
  template: `
   <ul id="photo-list">

      <!-- add :key="" directive -->
      <photo-item v-for="(photo, index) in photos" :key="index" :photo="photo"></photo-item>
   </ul>`
});


new Vue({
   el: "#photo_detail",

   // define used components
   components: {photoList},
   data: {
      photos: []
   },

   created: function() {

      // axios.get('/api/photos')
      // use arrow function
      setTimeout(() => {
		this.photos = [{name: 'Photo 1'}, {name: 'Photo 2'}];
      }, 1000);
   }
 })
<script src="https://unpkg.com/vue"></script>

<main id="photo_detail">
  <photo-list :photos="photos"></photo-list>
</main>

Upvotes: 0

Helping hand
Helping hand

Reputation: 2930

Issue is with your this value inside function() which has this value scoped to axios instead of vue instance . or you can use (response)=> to use this directly

new Vue({
   el: "#photo_detail",
   data: {
      photos: []
   },

   created: function() {
      var self=this;
      axios
       .get('/api/photos')
       .then(function (response) {
           self.photos = response.data; // Data existed
       })
       .catch(function (err) {
           console.log(err);
       });
   }
 })

Upvotes: 14

Related Questions