Reputation: 93
I'm trying to call loadPhotos, but I get an error saying that loadPhotos is not defined. I tried this.loadPhotos();
but then I get an error saying that the object doesn't have such a method. I'm pretty new at this and still trying to figure out what has access to what and such, and I'd greatly appreciate if someone could point me in the right direction. What am I doing wrong?
Here's my code:
Album = Backbone.Collection.extend ({
model: Photo,
url: "/api/",
albumName: "",
initialize: function(models, options){
options || (options = {});
if (options.title) {
this.albumName = options.title;
};
$.ajax({
type: "GET",
url: this.url,
data: "album=" + this.albumName,
dataType: "json",
success: function(data){
console.log(data);
loadPhotos(data); // <<< the problem is right here
},
error: function(jqXHR, textStatus, errorThrown){
console.log("FETCH FAILED: " + errorThrown);
}
});
},
loadPhotos: function(filenames){
for (var i = 0; i < filenames.length; i++ ){
var photo = new Photo( {fileurl: filenames[i] });
var photoView = new PhotoView( { model: photo} );
this.add(photo);
}
}
});
Upvotes: 3
Views: 6772
Reputation: 161517
You are misunderstanding how scoping and this
work in JavaScript.
Calling the function like
loadPhotos(data);
will look for a function called loadPhotos
in the various scopes from your success callback up to the global scope, but no such function exists because the function is attached to your collection instance.
this.loadPhotos(data)
is closer however it entirely depends on what this
is referencing. this
is a special keyword in JavaScript and the object that it points at depends on how the function was called. In your case this
depends entirely on the behavior of jQuery. You want to use a reference to the collection. Common names to make it easier to know that the variable references the object are self
, that
and sometimes _this
.
The one way to do that is a save a reference to the object pointed to by the outer this
that references the collection. If you save it into a variable, it will work fine.
initialize: function(models, options){
// Stuff
var self = this;
$.ajax({
type: "GET",
url: this.url,
data: "album=" + this.albumName,
dataType: "json",
success: function(data){
console.log(data);
// Call the function on the collection.
self.loadPhotos(data);
},
error: function(jqXHR, textStatus, errorThrown){
console.log("FETCH FAILED: " + errorThrown);
}
});
},
Another option is to do as @alnitak's answer says, and explicitly pass the proper callback context using the context
attribute.
Upvotes: 4
Reputation: 339917
If you call showPhotos
directly it will have the global context (i.e. window
).
If you just pass a reference to this.showPhotos
it won't work either because that won't establish that this
is to be used as the context when it's subsequently called.
To fix that, you also need to ask jQuery to set the right value of this
, which can be done with the context
option:
$.ajax({
...,
context: this,
success: this.loadPhotos,
error: ...
});
If your success does nothing except call loadPhotos
, setting the context
variable allows you to just pass the reference to that function directly (as above), instead of wrapping a call to it in another function body.
Upvotes: 4