I am in process of learning and using Backbone.js.
I have an Item model and a corresponding Item view. Each model instance has item_class and item_id attributes, that I want to be reflected in as the 'id' and 'class' attributes of the corresponding view. What's the correct way to achieve this ?
Example:
var ItemModel = Backbone.Model.extend({
});
var item1 = new ItemModel({item_class: "nice", item_id: "id1"});
var item2 = new ItemModel({item_class: "sad", item_id: "id2"});
var ItemView = Backbone.View.extend({
});
How should I implement the view so that the the views 'el's will translate to:
<div id="id1" class="nice"></div>
<div id="id2" class="sad"> </div>
In most examples I have seen, the view's el serves as a meaningless wrapper element inside which one has to manually write the 'semantic' code.
var ItemView = Backbone.View.extend({
tagName: "div", // I know it's the default...
render: function() {
$(this.el).html("<div id="id1" class="nice"> Some stuff </div>");
}
});
So when rendered, one gets
<div> <!-- el wrapper -->
<div id="id1" class="nice"> Some stuff </div>
</div>
But this seems like a waste - why have the external div ? I want the el to translate directly into the internal div!
The other examples are not showing how to actually grab the data from the model. To dynamically add id and class from the model's data:
In your view just do something like this
Here's a minimal way to change the class of the view's element dynamically via a model and update it on model changes.
You need to remove tagName and declare an el.
'tagName' signifies that you want backbone to create an element. If the element already exists in the DOM, you can specify an el like:
and later:
Summary: dynamically set view attributes with model data
http://jsfiddle.net/5wd0ma8b/
This example assumes that you're allowing Backbone to generate a DOM element for you.
The
attributes
method is called after the properties passed to the view constructor are set (in this case,model
), allowing you to dynamically set the attributes with the model data before Backbone createsel
.In contrast to some of the other answers: doesn't hard-code attribute values in the view class, dynamically sets them from model data; doesn't wait until
render()
to set attr vals; doesn't repeatedly set attr vals in every call torender()
; doesn't unnecessarily manually set attr vals on DOM element.Note that if setting the class when calling
Backbone.View.extend
or a view constructor (e.g.new Backbone.View
), you have to use the DOM property name,className
, but if setting it via theattributes
hash / method (as in this example) you have to use the attribute name,class
.As of Backbone 0.9.9:
I mention this in case there's a situation where that would be useful as an alternative to using an
attributes
method as illustrated.Using an existing element
If you're using an existing element (e.g. passing
el
to the view constructor)......then
attributes
won't be applied to the element. If the desired attributes aren't already set on the element, or you don't want to duplicate that data in your view class and another location, then you may want to add aninitialize
method to your view constructor that appliesattributes
toel
. Something like this (usingjQuery.attr
):Usage of
el
, rendering, avoiding the wrapperThere's no reason
view.el
needs to be "a meaningless wrapper element". In fact, that would often break the DOM structure. If a view class represents a<li>
element for example, it needs to be rendered as an<li>
-- rendering it as a<div>
or any other element would break the content model. You'll likely want to focus on correctly setting up your view's element (using properties liketagName
,className
, andid
) and then rendering its content thereafter.The options for how to have your Backbone view objects interact with the DOM are wide open. There are 2 basic initial scenarios:
You can attach an existing DOM element to a Backbone view.
You can allow Backbone to create a new element that is disconnected from the document, then somehow insert it into the document.
There are various ways you can generate the content for the element (set a literal string, as in your example; use a templating library like Mustache, Handlebars, etc.). How you should use the
el
property of the view depends what you're doing.Existing element
Your rendering example suggests that you have an existing element that you're assigning to the view, although you don't show instantiation of the views. If that's the case, and the element is already in the document, then you may want to do something like this (update the content of
el
, but don't alterel
itself):http://jsfiddle.net/vQMa2/1/
Generated element
Let's say you don't have an existing element and you allow Backbone to generate one for you. You may want to do something like this (but it's likely better to architect things so that your view isn't responsible for knowing about anything outside itself):
http://jsfiddle.net/vQMa2/
Templates
In my case, I'm using templates, e.g.:
The template represents the complete view. In other words, there will be no wrapper around the template --
div.player
will be the root or outermost element of my view.My player class will look something like this (with very simplified example of
render()
):I know it's an old question, but added for reference. This seems to be easier in new backbone versions. In Backbone 1.1 the id and className properties are evaluated in the function
ensureElement
(see from source) using underscore_.result
meaning ifclassName
orid
is a function, it will be called, otherwise its value will be used.So you could give className directly in the constructor, give another parameter that would be used in the className, etc... Plenty of options
so this should work