kramer65
kramer65

Reputation: 53933

How to poll to update a Backbone underscore template?

I'm building a website with the Javascript Backbone framework and the standard underscore templating engine. I've got a listview which I load upon the first page load. Since the contents of this list may change server side, I want to update this list every two seconds. I tried doing this by adding a setInterval call:

var OpenTicketListView = Backbone.View.extend({
    el: '#the-id-in-the-template',
    render: function() {
        var that = this;
        var tickets = new TicketColection();
        tickets.fetch({
            success: function(openTickets){
                console.log('WE GOT A RESPONSE!');
                var template = _.template($('#my-template').html(), {tickets: tickets.models});
                that.$el.html(template);
            }
        });
    }
});

var openTicketListView = new OpenTicketListView();

router.on("route:home", function() {
    openTicketListView.render();
    assignedTicketListView.render();
});

setInterval(openTicketListView.render, 2000);

This setup seems to ALMOST work. The listview renders perfectly fine the first time. The setInterval also seems to work, since it gets updated lists from the server, which look good (with updated content) in the console. I also see the "WE GOT A RESPONSE!" in the console. BUT, the only thing that it refuses to do, is update the view visually.

Does anybody know what I might be doing wrong here? What is the stupidity that I'm on here? How can I possibly debug this?

All tips are welcome!

Upvotes: 0

Views: 834

Answers (1)

levi
levi

Reputation: 25141

The problem is, the value of this inside the render function is being lost when you call the function from setInterval. One way of solving that would be to bind the context to the function:

setInterval(openTicketListView.render.bind(openTicketListView), 2000);

Its worth noting, there is no need to call the render function directly. Instead, you can call fetch from the polling method, and have the view bind to the collection's sync event, and re-render itself. Something like this:

var OpenTicketListView = Backbone.View.extend({
    el: '#the-id-in-the-template',
    initialize: function() {
        this.listenTo(this.collection, 'sync', this.render);
        this.collection.fetch();
    },
    render: function() {
        console.log('WE GOT A RESPONSE!');
        var template = _.template($('#my-template').html(), {tickets: this.collection.models});
        that.$el.html(template);
    }
});

var tickets = new TicketColection();
var openTicketListView = new OpenTicketListView({ collection: tickets });

setInterval(tickets.fetch.bind(tickets), 2000);

Upvotes: 1

Related Questions