I have a Backbone Collection that needs to fetch whenever another Backbone Model (no part of the Collection) changes.
When I write it like this:
this.fModel = new FooModel();
this.bCollection = new BarCollection();
this.fModel.on("change", this.bCollection.fetch, this)
I get the following error when the change event is triggered:
Uncaught TypeError: Object #<Object> has no method 'trigger'
However, when I simply wrap the Collection's fetch call, it works as expected:
this.fModel = new FooModel();
this.bCollection = new BarCollection();
this.testfunc = function(){
this.bCollection.fetch();
}
this.fModel.on("change", this.testfunc, this)
Why is this the case? Thanks!
This is a fun one to try and explain :)
So when you call on
like this:
this.fModel.on('change', this.bCollection.fetch, this);
You are setting the context that fetch
is run in to whatever this
is. In this code it looks like this
is simply your top-level application or similar. fetch
can't do much with that! Let's look at the implementation of fetch
:
// Fetch the default set of models for this collection, resetting the
// collection when they arrive. If `add: true` is passed, appends the
// models to the collection instead of resetting.
fetch: function(options) {
options = options ? _.clone(options) : {};
if (options.parse === undefined) options.parse = true;
var collection = this;
var success = options.success;
options.success = function(resp, status, xhr) {
collection[options.add ? 'add' : 'reset'](collection.parse(resp, xhr), options);
if (success) success(collection, resp);
};
options.error = Backbone.wrapError(options.error, collection, options);
return (this.sync || Backbone.sync).call(this, 'read', this, options);
},
So we basically make it up to var collection = this;
... Oops!
We've set collection
inside fetch
to be your top-level application!
So the reason it works when you wrap it is even more fun:
var wrapped = function() { this.bCollection.fetch(); };
this.fModel.on('change', wrapped, this);
We've set the context of wrapped
to be this
. That's fine because this.bCollection
is exactly what we want. But when you call fetch
on bCollection
here, it's doing it in the normal way, binding this
inside it to the object it was called on - this is normal javascript stuff now.
So, here's a TL;DR:
You actually want:
this.fModel.on('change', this.bCollection.fetch, this.bCollection);
Because the context of the fetch
function call should be the collection itself, and nothing else.
Make sense?
Cheers :)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.