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'); } }); ```

Original source