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!
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.
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.
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.
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>
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With