Reputation: 38802
I do an extensive use of templates, and I like to use full contained templates. I mean that I want to see in the template code all the DOM elements including the root one, like this:
<script type="text/template" id="template-card">
<div class="card box" id="card-<%= id %>">
<h2><%= title %></h2>
<div><%= name %></div>
</div>
</script>
But what Backbone likes is having a template like this:
<script type="text/template" id="template-card">
<h2><%= title %></h2>
<div><%= name %></div>
</script>
And defining the root element and its attributes in the JS code. What I think is ugly and confusing.
So, any good way to avoiding my Backbone View to wrapper my template with an extra DOM element?
I have been checking this issue thread: https://github.com/documentcloud/backbone/issues/546 and I understand there is not any official way to do it.. but maybe you can recommend me a non official way.
Upvotes: 25
Views: 6573
Reputation: 33344
You can take advantage of view.setElement
to render a complete template and use it as the view element.
setElement view.setElement(element)
If you'd like to apply a Backbone view to a different DOM element, use setElement, which will also create the cached $el reference and move the view's delegated events from the old element to the new one
Two points you have to account for:
setElement
calls undelegateEvents
, taking care of the view events, but be careful to remove all other events you might have set yourself.setElement
doesn't inject the element into the DOM, you have to handle that yourself.That said, your view could look like this
var FullTemplateView = Backbone.View.extend({
render: function () {
var html, $oldel = this.$el, $newel;
html = /**however you build your html : by a template, hardcoded, ... **/;
$newel = $(html);
// rebind and replace the element in the view
this.setElement($newel);
// reinject the element in the DOM
$oldel.replaceWith($newel);
return this;
}
});
And a working example to play with http://jsfiddle.net/gNBLV/7/
Upvotes: 42
Reputation: 7225
Backbone.Decarative.Views provides you with an alternative way to do this, without having to rely on setElement
. For more, check out my answer here.
Upvotes: 0
Reputation: 2512
Now you can also define a view's tagName as a function and create a class like this:
var MyView = Backbone.View.extend({
template: '#my-template',
tagName: function() {
// inspect the template to retrieve the tag name
},
render: function() {
// render the template and append its contents to the current element
}
});
Here's a working example
Upvotes: 0