Backbone.js updating of models in a collection

14,570

Solution 1

Lets assume that every one of your tweets has a unique identifier(if not, you should probably create one).

You can structure your backend in such away that by default it gets you 10 latest tweets if you call http://your.site.com/tweets without any arguments.

If you however call http://your.site.com/tweets?last_tweet_id=BLAblaBlA, it will give you 10 latest tweets that came after the last_tweet_id that you specified.

You can override the code that gets the data from the backend into your Collection by implementing YourCollection.sync method.

Reason: Backbone.Collection first tries to call Collection.sync and if its not implemented, it calls Backbone.sync function, so if you implement YourCollection.sync, it will be used. Here is the snippet from Backbone.Collection.fetch function:

(this.sync || Backbone.sync)('read', this, success, error);

so your sync would be something like

var TweetCollection = Backbone.Collection.extend({
  model: TweetModel,
  sync: function(method, collection, success, error) {
    var requestData={};
    if(collection.length>0) {
        requestData.last_tweet_id=collection.last.id 
    }
    var params = {
        url:          "/tweet",
        type:         "POST",
        data:         requestData,
        success:      success,
        error:        error
    };
    $.ajax(params);
  }
}

You would have to override your collections parse function to make sure that the response is appended to the existing array of models.

Solution 2

I'm not sure if this was possible back in March as I only recently started using backbone. But a better solution may be to pass standard jQuery options into Collection.fetch.

this.collection.fetch({data: {last_tweet: last_teet_id}});

Check out the jQuery documentation for a full list of parameters.

Solution 3

I believe this is what you were looking for:

yourCollection.fetch({add: true})

Then, you can bind your collection view's render to the add event:

yourCollectionView.bind('add', this.render, this);

Though, if the render is heavy, you'll want to delay it with a timeout to avoid immediately calling it for every addition to the collection:

yourCollectionView.bind('add', this.delayedRender, this);

delayedRender: function() {
  var self = this;
  if (self.renderTimer) { clearTimeout(self.renderTimer); }
  self.renderTimer = setTimeout(function() {
    self.render();
    self.renderTimer = null;
  }, 300);
}
Share:
14,570

Related videos on Youtube

Honza Pokorny
Author by

Honza Pokorny

Updated on June 04, 2022

Comments

  • Honza Pokorny
    Honza Pokorny almost 2 years

    Let's say you are building a Twitter clone with Backbone.js. You have a collection of tweets. Each tweet is obviously an instance of the Tweet model.

    You create an instance of the collection, fetch the latest 10 tweets, render them and add to the DOM.

    So far so good.

    What if you wanted to make a call to the server a few minutes later to see if any new tweets arrived? How can you add the newly arrived tweets to the collection?

    If you use the fetch() method, you are hitting the same URL all the time. That's fine. Is there a clever way that I can use Backbone/Underscore to filter those and add the tweets that aren't in the collection to the collection?

  • Honza Pokorny
    Honza Pokorny about 13 years
    This is not about building an interface to Twitter. It's a Twitter-like application.
  • Tim Gilbert
    Tim Gilbert about 11 years
    I'm curious why you're specifying POST as the http method here. Wouldn't GET be more conventional from a REST perspective?

Related