Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Underscore templating help needed - templating collections

I'm using underscore.js for templating. Here is a sample template.

<script id="discussion-template" type="text/html">
    [[ _.each(discussions, function(topic){ ]]
       <li>
           <article id="{{ topic.htmlId() }}">
               <a class="section-arrow mir" href="#">toggle</a>
               <h3>{{ topic.get('text') }}</h3>
               <ol></ol>
           </article>           
       </li>
    [[ }); ]]
</script>

Inside a backbone.js view.render() I'm passing a collection to the template.

this.el.append(this.template({ discussions: this.collection.models }));

My question here is , do I have to write the looping code? Can I not just pass in a collection and underscore be smart enough to render one item per item in collection? Also does underscore.js provide something for nesting templates? Each item in the collection actually has a collection of items I will need to render as well. How can I call another template from within this template. Any links, tips, and or tutorials are of course greatly appreciated.

Thanks!

like image 972
Hcabnettek Avatar asked Oct 18 '11 21:10

Hcabnettek


People also ask

What is underscore template?

The _. template() function is an inbuilt function in the Underscore. js library of JavaScript which is used to compile JavaScript templates into functions that can be evaluated for rendering.

What is the use of underscore in node js?

Underscore. js is a utility library that is widely used to deal with arrays, collections and objects in JavaScript. It can be used in both frontend and backend based JavaScript applications. Usages of this library include filtering from array, mapping objects, extending objects, operating with functions and more.

What are underscore functions?

Underscore. JS is a popular javascript based library which provides 100+ functions to facilitate web development. It provides helper functions like map, filter, invoke as well as function binding, javascript templating, deep equality checks, creating indexes and so on.


2 Answers

I think you do have to write the looping code, but you could clean it up by having the loop in the view rather than the template. So you'd have one template for the container (that holds the <ol>) and another for rendering <li>s.

For the each item being a collection of items you can use the same technique, with those models appending to the <ol class="topic-collection-will-append-to-this"> in the topic item template.

I didn't test the code below so I'm not 100% it's not bug free, but it should give you idea of a way to tackle it :)

window.TopicView = Backbone.View.extend({
    template: _.template($("#topic-template").html()),
    tag: 'li',
    className: 'topic',

    initialize: function() {
        _.bindAll(this, 'render');
    },

    render: function() {
        $(this.el).html(this.template({topic: this.model}));
        return this;
    }
});

window.DiscussionView = Backbone.View.extend({
    tagName: 'section',
    className: 'discussion',
    template: _.template($('#discussion-template').html()),

    initialize: function() {
        _.bindAll(this, 'render');
        this.collection.bind('reset', this.render);
    },

    render: function() {
        var $topics,
        collection = this.collection;

        $(this.el).html(this.template({}));
        $topics = this.$(".topics");
        this.collection.each(function(topic) {
            var view = new TopicView({
                model: topic
            });
            $topics.append(view.render().el);
        });

        return this;
    }
});

<script id="topic-template" type="text/html">
    <article id="{{ topic.htmlId() }}">
        <a class="section-arrow mir" href="#">toggle</a>
        <h3>{{ topic.get('text') }}</h3>
        <ol class="topic-collection-will-append-to-this">
        </ol>
    </article>           
</script>

<script type="text/template" id="discussion-template">
    ...
    <ol class="topics">
    </ol>
</script>
like image 139
kreek Avatar answered Sep 28 '22 06:09

kreek


You can have two templates, one for the list and one for the inner elements. And in the list template just print the result of the inner one: http://jsfiddle.net/dira/hRe77/8/

Underscore's templates are very very simple and don't have any smart behaviour/magic attached: http://documentcloud.github.com/underscore/docs/underscore.html#section-120

like image 25
dira Avatar answered Sep 28 '22 05:09

dira