Locohost
Locohost

Reputation: 1702

Backbone/Underscore _.each(...) doesn't seem to work according to docs

In this code...

_.each(this.photos, function(element,index,list) {
    console.log('element...');
    console.log(element);
    var photoView = new PhotoView({photo:element});
    self.$el.append(photoView.render());
});

element is the entire this.photos collection. Why is not just one photo element of the 10 in the collection?

EDIT: Here is my method that populates the photos collection....

loadPhotos: function(memberId) {
    var self = this;
    this.photos = new PhotosCollection([]); 
    this.photos.on('error', this.eventSyncError, this);
    this.photos.fetch({
        url: this.photos.urlByMember + memberId, 
        success: function(collection,response,options) {
            console.log('Fetch photos success!');
            self.render();
        }
    });
},

The collection loads with models just fine. In the Chrome console, I can see the collection of models. I'm not sure what's wrong. I cannot iterate the collection with any of the methods recommended by posters below.

Upvotes: 1

Views: 497

Answers (3)

Locohost
Locohost

Reputation: 1702

Thank you for your suggestions! I would never have figured this out without all your advice above. So here was the problem...

In the parent view, this loads up photo records for a particular member...

loadPhotos: function(memberId) {
    var self = this;
    this.photos = new PhotosCollection([]); 
    this.photos.on('error',this.eventSyncError,this);
    this.photos.fetch({
        url: this.photos.urlByMember + memberId, 
        success: function(collection,response,options) {
            self.render();
        } 
    });
},

Still in the parent view, Backbone.Subviews uses this to call each child view when it renders. Note how I'm passing this.photos to the subvw-photos...

subviewCreators: {
    "subvw-profile": function() {
        var options = {member: this.member};
        // do any logic required to create initialization options, etc.,
        // then instantiate and return new subview object
        return new ProfileView( options );
    },
    "subvw-photos": function() {
        var options = {photos: this.photos};
        return new PhotosView( options );
    },
    "subvw-comments": function() {
        var options = {};
        return new CommentsView( options );
    }
},

This is in the subvw-photos child view. Note how the intialize is accepting the collection as a parameter. See this problem?...

initialize: function(photos) {
    Backbone.Courier.add(this);
    this.photos = photos;
},

render: function() {
    console.log('rendering photosview now...');
    var self = this;
    this.photos.each(function(element,index,list) {
        var photoView = new PhotoView({photo:element});
        $(self.el).append(photoView.render());
    });
    return this;
},

I was passing an object wrapping the photos collection in to initalize but then treating it like it was just a ref to the photos collection. I had to change the subvw-photos initialize to the following...

initialize: function(args) {
    Backbone.Courier.add(this);
    this.photos = args.photos;
},

Then of course all the other code magically began working :-/

Thank you again for your tips! You definitely kept me on track :-)

Upvotes: 0

denz
denz

Reputation: 386

One should use this.photos.each(function(elt, index, list){...}) instead of _.each(this.photos,...) because this.photos is not an underscorejs _.chain object.

Upvotes: 0

nemesv
nemesv

Reputation: 139758

You are using the _.each method incorrectly. The underscore methods needs to called directly on the collection:

this.photos.each(function(element,index,list) {
    console.log('element...');
    console.log(element);
    var photoView = new PhotoView({photo:element});
    self.$el.append(photoView.render()); 
});

Or you if want to use the _.each from you need to pass in the models property and not the collection object itself as the list:

_.each(this.photos.models, function(element,index,list) {
    console.log('element...');
    console.log(element);
    var photoView = new PhotoView({photo:element});
    self.$el.append(photoView.render());
});

Upvotes: 3

Related Questions