Updating the DOM with change in an object (vue.js) - binding not working?

8.9k views Asked by At

I have the app.js file where gmarkers is an array of objects :

var vm = new Vue({
    el: '#lili',
    data: {
        listings: gmarkers
    }
});

In my HTML file :

<div id="lili" >
    <div
        v-repeat="gmarker : listings" 
        class="listing listing-list col-sm-12" 
        style="height:50px;line-height:50px;"  
        data-cat="@{{gmarker.mycategory}}" 
        data-id="@{{gmarker.id}}"
    >
        <span style="color:black;">
            <a target="_blank" href="@{{gmarker.listlink}}">
                @{{ gmarker.listname }}
            </a>
        </span>
        <span class="tag blue-back" style="margin-left:5px;">
            <a target="_blank" href="@{{gmarker.catlink}}">
                @{{gmarker.listcat}}
            </a>
        </span>
        <span style="margin-left:20px;color:#bbb;">
            @{{gmarker.distance}}km
        </span>
    </div>
</div>

When loading the page, the DOM loads correctly, displaying the list I'm looking for but when (after an ajax call in js) the gmarkers object changes, the DOM doesn't change.

The new gmarkers is totally created from scratch and containing new objects.

What am I missing ?

1

There are 1 answers

2
DutGRIFF On BEST ANSWER

It sound like you are wrong about what data is being bound here. You are expecting data: {listings: gmarkers} to do binding between vm.listings and the gmarkers array. This isn't what it does. It copies the gmarkers data into the listings and doesn't listen to gmarkers anymore. See this fiddle for an example of what I think you are doing wrong.

We can fix the above fiddle by setting the vm.listings to the new array of objects after the ajax request.

vm.$set('listings', gmarkers);

You can see this in action in this updated fiddle.

It is actually pretty common to see a blank listings until ajax returns them. Here is some sample code that will call an ajax request when vue is ready and update the listings once it is finished. Note: this exampe uses vue-resources to perform the ajax request. You may not have this. You can always just use jQuery or javascript to perform this.

data: {
    listings: []
},
ready: function () {
  this.fetchListings();
},
methods: {
  fetchListings: function () {
    this.$http.get('/your/api/listings', function (response) {
      this.$set('listings', response);
    });
  }
}

This fiddle shows the above code but pay attention to the differences required for the fake ajax request I used.