Render html table with underscore template engine using a backbone complex model
backbone.js, underscore.js
Solution
First, I would parse the data into the collection to get a list of the pages and maybe grab the `CurrentModel` definition :
var PageCollection = Backbone.Collection.extend({
url: '/pages',
model: Page,
parse: function(response) {
this.CurrentModel=new Page(response.CurrentModel);
return response.Children;
}
});
Then, with the row template set up as
<script id="tpl-page-list-item" type="text/template">
<tr>
<td><%= Metadata.Name %></td>
<td><%= Metadata.Slug %></td>
<td><%= Metadata.IsPublished %></td>
<td><%= Metadata.Changed %></td>
<td><input type='checkbox' /></td>
</tr>
</script>
you can define your views more or less like you had them
var PageListItemView = Backbone.View.extend({
template: _.template($('#tpl-page-list-item').html()),
events: {
"click input[type=checkbox]": "publish"
},
render: function (eventName) {
var html=this.template(this.model.toJSON());
this.setElement($(html));
return this;
},
publish: function () {
console.log(this.model.get("Metadata").Name);
}
});
var PageListView = Backbone.View.extend({
tagName: 'table',
initialize: function () {
this.collection.bind("reset", this.render, this);
},
render: function (eventName) {
this.$el.empty();
this.collection.each(function(page) {
var pageview=new PageListItemView({ model: page });
var $tr=pageview.render().$el;
this.$el.append($tr);
},this);
return this;
}
});
Initialize the collection and the views, fetch the data, and you should have something equivalent to this Fiddle : http://jsfiddle.net/NtmB4/
var coll=new PageCollection();
var view=new PageListView({collection:coll})
$("body").append(view.render().el);
coll.fetch();
And a Fiddle corresponding to your full template http://jsfiddle.net/NtmB4/2/
Problem
I'm trying to render an html table using underscore template engine. First I have the JSON response from the server like this ``` { CurrentModel: { Heading: "Home", Id: "pages/193", Metadata: { Name: "Home", Title: null, Keywords: null, Description: null, DisplayInMenu: true, Published: "/Date(1334499539404)/", Changed: "/Date(1334499539404)/", ChangedBy: "Marcus", IsPublished: true, IsDeleted: false, Slug: null, Url: null, SortOrder: 0 }, Parent: null, Children: [ "pages/226", "pages/257" ] }, Children: [ { Heading: "Foo", MainBody: null, Id: "pages/226", Metadata: { Name: "I'm an article", Title: null, Keywords: null, Description: null, DisplayInMenu: true, Published: "/Date(1334511318838)/", Changed: "/Date(1334511318838)/", ChangedBy: "Marcus", IsPublished: true, IsDeleted: false, Slug: "i-m-an-article", Url: "i-m-an-article", SortOrder: 1 }, Parent: {}, Children: [ ] }, { Heading: "Bar", MainBody: null, Id: "pages/257", Metadata: { Name: "Foo", Title: null, Keywords: null, Description: null, DisplayInMenu: true, Published: "/Date(1334953500167)/", Changed: "/Date(1334953500167)/", ChangedBy: "Marcus", IsPublished: true, IsDeleted: false, Slug: "foo", Url: "foo", SortOrder: 2 }, Parent: {}, Children: [ ] } ] } ``` The HTML result I'm looking for is pretty much like this where i print some of the data from the CurrentModel and the iterate through the Children property, preferably each tr in the the tbody should be a view using backbone.js so I can wire up some events for this particular row. ``` <table> <caption><%= CurrentModel.Metadata.Name %></caption> <thead> <tr> <th><span>Page name</span></th> <th><span>Slug</span></th> <th><span>Published</span></th> <th><span>Changed</span></th> </tr> </thead> <tbody> <% _(Children).each(function(page) { %> <tr> <td><%= page.Metadata.Name %></td> <td><%= page.Metadata.Slug %></td> <td><%= page.Metadata.IsPublished %></td> <td><%= page.Metadata.Changed %></td> </tr> <% }); %> </tbody> </table> ``` Now, my question is how should my backbone views and models look like or is it not meant to be used like this? The javasscript code below works and renders a tr for each Children if the response from the server is just a Collection of Page, I understand way but I don't know how to modify the code so it can take a complex model and then render parts of that model in one or maybe two javascript views? In my application.js I have this code ``` pages: function () { this.pageList = new PageCollection(); this.pageListView = new PageListView({ model: this.pageList }); this.pageList.fetch(); } ``` where PageCollection looks like this ``` var PageCollection = Backbone.Collection.extend({ url: '/pages', model: Page }); ``` the model class like this ``` Page = Backbone.Model.extend({ metadata: { name: null, title: null, keywords: null, description: null, displayInMenu: null, published: null, changed: null, changedBy: null, isPublished: null, isDeleted: null, slug: null, url: null, sortOrder: null }, parent: {}, children: [], ancestors: null, initialize: function () { } }); ``` the PageListView ``` PageListView = Backbone.View.extend({ tagName: 'table', initialize: function () { this.model.bind("reset", this.render, this); }, render: function (eventName) { _.each(this.model.models, function (page) { $(this.el).append(new PageListItemView({ model: page }).render().el); }, this); return this; } }); ``` and at last the PageListItemView ``` PageListItemView = Backbone.View.extend({ tagName: "tr", template: _.template($('#tpl-page-list-item').html()), events: { "click td input[type=checkbox]": "publish" }, render: function (eventName) { $(this.el).html(this.template(this.model.toJSON())); return this; }, publish: function (event) { alert('Publish'); } }); ```