68

In my backbone.js app, there is a Trips collection that holds Trip models, which is working with LocalStorage. I am able to call Trips.create(form_attributes) to create and save a trip to the Todos store.

When I first load my app, I call Trips.fetch({ success: trips_fetch_success }), and trips_fetch_success receives a response that shows the Trip models that the Trips collection holds.

I have tried to bind refresh and change events to the Trips collection, but these events are not being caught, making me believe I have the wrong idea about which events Trips.fetch triggers.

My question: which events should Trips.fetch trigger? And are the events triggered on the collection or on each of the individual Trip models?

alex
  • 479,566
  • 201
  • 878
  • 984
Alan David Garcia
  • 1,523
  • 2
  • 14
  • 23

3 Answers3

59

Collection.fetch() will call reset on success, which in turn will trigger a 'reset' event. Any subscribers to the collections reset event should receive the event.

The key here is "on success." I had this problem, only to discover that backbone was silently swallowing my errors messages. Pass in an error handler that, at least, logs to console.log(), and see what's happening:

trips.fetch({error: function() { console.log(arguments); }});

(Note: Old versions of backbone.js will trigger "refresh" instead of "reset")

alex
  • 479,566
  • 201
  • 878
  • 984
Elf Sternberg
  • 16,129
  • 6
  • 60
  • 68
  • 4
    You can have a global jQuery ajax error handler to handle errors of this kind, usually related to connectivity issues. – Julien Mar 11 '11 at 15:19
  • 9
    As of backbone 0.5+, `Collection#refresh` [was renamed](http://documentcloud.github.com/backbone/#changelog) to `Collection#reset`. The event is also renamed accordingly. – ejel Jul 23 '11 at 20:40
  • 1
    Also, useful to know that the `reset` callback has two default arguments `"reset" (collection, options)` and it is triggered when the collection's entire contents have been replaced.` – Alan David Garcia Apr 03 '13 at 15:31
52

If you are using backbone 1.0, you'll need to pass reset:true in the fetch() call in order to bind with the reset event:

trips.fetch({reset: true});
jesal
  • 7,852
  • 6
  • 50
  • 56
  • 6
    good point. When I wish to refresh a view based on a model fetch(), I bind to 'sync'. That's what is triggered by default in 1.0. – Perry Tew Jun 11 '13 at 21:14
20

As of backbone 1.0, model.fetch() triggers a 'sync'. That's what you should bind to.

Here's the relevant part from the backbone.js source where the 'sync' event is fired:

fetch: function(options) {
  options = options ? _.clone(options) : {};
  if (options.parse === void 0) options.parse = true;
  var model = this;
  var success = options.success;
  options.success = function(resp) {
    if (!model.set(model.parse(resp, options), options)) return false;
    if (success) success(model, resp, options);

    // HERE'S THE TRIGGER!
    model.trigger('sync', model, resp, options);

  };
  wrapError(this, options);
  return this.sync('read', this, options);
},
morten.c
  • 3,414
  • 5
  • 40
  • 45
Perry Tew
  • 2,632
  • 3
  • 22
  • 25
  • 2
    that's the actual code from the backbone.js source, btw. I just re-read my comment and wondered what the code was myself... Better to be explicit. – Perry Tew Dec 06 '13 at 01:51