Handlebars won't loop over my Backbone.js Collection
I have a Backbone app where I'm attempting to populate a collection using a JSON file. I want to generate a list of "titles" from the JSON to eventually turn into a menu. Everything is going well, except that Handlebars won't loop (each) over my collection to render the list.
The relevant view:
var MenuView = Backbone.View.extend({
template: Handlebars.compile(
'<ul>' +
'{{#each items.models}}<li>{{attributes.title}}</li>{{/each}}' +
'</ul>'
),
initialize: function () {
this.listenTo(this.collection, "reset", this.render);
},
render: function () {
this.$el.html(this.template(items));
return this;
}
});
The model and collection:
var Magazine = Backbone.Model.extend({
urlRoot:"/items",
defaults: {
id: '',
title: '',
pubDate: '1/1',
image: ''
}
});
var MagazineMenu= Backbone.Collection.extend({
comparator: 'title',
model: Magazine,
url: "/items"
});
The router:
var MagazineRouter = Backbone.Router.extend({
routes: {
"" : "listPage",
"titles/:id" : "showTitle"
},
initialize: function () {
this.magazineModel = new Magazine();
this.magazineModel.fetch();
this.magazineView = new MagazineView({
model: this.magazineModel
});
this.magazineCollection = new MagazineMenu();
this.magazineCollection.fetch();
this.menuView = new MenuView({collection: this.magazineCollection});
},
showTitle: function(id) {
this.magazineModel.set("id", id);
$("#theList").html(this.magazineView.render().el);
},
listPage : function() {
$('#theList').html(this.menuView.render().el);
}
});
var router = new MagazineRouter();
$(document).ready(function() {
Backbone.history.start();
});
And finally the JSON:
[
{
"id": "screamingzebras",
"url": "screamingzebras",
"title": "Screaming Zebras",
"pubDate": "2/1",
"image": "screamingzebras.jpg"
},
{
"id": "carousellovers",
"url": "carousellovers",
"title": "Carousel Lovers",
"pubDate": "3/1",
"image": "carousellovers.jpg"
},
{
"id": "gardenstatuary",
"url": "gardenstatuary",
"title": "Garden Statuary",
"pubDate": "4/1",
"image": "gardenstatuary.jpg"
},
{
"id": "sombreromonthly",
"url": "sombreromonthly",
"title": "Sombrero Monthly",
"pubDate": "1/1",
"image": "sombreromonthly.jpg"
}
]
When I run this in a browser, I get no errors in the console. If I console.log(this.collection)
just before the call to this.$el.html(this.template(items));
in the view, I can see the collection with a models attribute that is properly populated from the JSON. When I look at the Elements panel in Chrome dev tools, I can see that it is generating everything up to and including the <ul>
tag. That leads me to believe that I'm just missing a key logic point that is getting the Handlebars each function to actually loop over the collection.
I see two problems here:
items
isn't defined anywhere so your render
is really saying this.template(undefined)
. items
, your Handlebars template won't know that you've called it items
so it won't know that {{#each items.models}}
should iterator over it. Presumably your items
is really supposed to be the view's this.collection
and your render
should look more like this:
render: function () {
this.$el.html(this.template(this.collection));
return this;
}
That should solve problem 1 . You can fix problem 2 in two ways:
this.template
so that items
is associated with the right thing. The first option would use the above render
and a template that looks like this:
<ul>
{{#each models}}
<li>{{attributes.title}}</li>
{{/each}}
</ul>
The second option would leave your template alone but change render
to use:
this.$el.html(
this.template({
items: this.collection
})
);
Another option would be to use this.collection.toJSON()
to supply data to the template, then render
would use:
this.$el.html(
this.template({
items: this.collection.toJSON()
})
);
and then template would be:
<ul>
{{#each items}}
<li>{{title}}</li>
{{/each}}
</ul>
链接地址: http://www.djcxy.com/p/61592.html