I have 2 different templates for my model's views. Each time the models are fetched from the database, the first 3 models (#1, 2, 3) fetched from the backend will have the view created using the first template, the next 4 models (#4, 5, 6, 7) will use the second template, the next 3 models (#8, 9, 10) will use the first template and so on.
Problem: How will I introduce this alternating template using backbone.js?
JS Code
// Views
PhotoListView = Backbone.View.extend({
el: '#photo_list',
render: function() {
$(this.el).html('');
_.each(this.model.models, function(photo) {
$(this.el).append(new PhotoListItemView({ model: photo }).render().el);
}, this);
return this;
}
});
PhotoListItemView = Backbone.View.extend({
tagNAme: 'div',
className: 'photo_box',
template: _.template( $('#tpl_PhotoListView').html() ),
initialize: function() {
this.model.bind('destroy', this.close, this);
},
render: function() {
$(this.el).html( this.template( this.model.toJSON() ) );
return this;
},
close: function() {
this.unbind();
this.remove();
}
});
I have 2 different templates for my model's views. Each time the models are fetched from the database, the first 3 models (#1, 2, 3) fetched from the backend will have the view created using the first template, the next 4 models (#4, 5, 6, 7) will use the second template, the next 3 models (#8, 9, 10) will use the first template and so on.
Problem: How will I introduce this alternating template using backbone.js?
JS Code
// Views
PhotoListView = Backbone.View.extend({
el: '#photo_list',
render: function() {
$(this.el).html('');
_.each(this.model.models, function(photo) {
$(this.el).append(new PhotoListItemView({ model: photo }).render().el);
}, this);
return this;
}
});
PhotoListItemView = Backbone.View.extend({
tagNAme: 'div',
className: 'photo_box',
template: _.template( $('#tpl_PhotoListView').html() ),
initialize: function() {
this.model.bind('destroy', this.close, this);
},
render: function() {
$(this.el).html( this.template( this.model.toJSON() ) );
return this;
},
close: function() {
this.unbind();
this.remove();
}
});
Share
Improve this question
edited Jul 4, 2012 at 20:46
Nyxynyx
asked Jul 4, 2012 at 20:30
NyxynyxNyxynyx
63.6k163 gold badges506 silver badges855 bronze badges
1 Answer
Reset to default 20First of all, your PhotoListView
is wrapping a collection so you should be using this.collection
inside the view and new PhotoListView({ collection: c })
to create it. Views treat the collection
option similarly to how they treat model
:
constructor / initialize
new View([options])
[...] There are several special options that, if passed, will be attached directly to the view:
model
,collection
,el
,id
,className
,tagName
and attributes.
Using the right names will help prevent confusion. Also, views have some Underscore methods already mixed in so you can say this.collection.each(...)
instead of _.each(this.collection.models, ...)
or _(this.collection.models).each(...)
. You can also use this.$el
instead of $(this.el)
.
And now on to your real problem. You can add two templates to your per-model view:
PhotoListItemView = Backbone.View.extend({
template0: _.template($('#the-first-template-id').html()),
template1: _.template($('#the-other-template-id').html()),
//...
});
and an option to tell it which one to use:
initialize: function(options) {
this.template = this['template' + options.template_number];
//...
}
Then you just need to specify the group
option from the collection view. Underscore's each
passes the iteration index to the callback function as the second argument so you just need a bit of integer math to figure out which template_number
to use:
this.collection.each(function(photo, i) {
// Grouped in threes and you're alternating between two templates.
var n = Math.floor(i / 3) % 2;
var v = new PhotoListItemView({ model: photo, template_number: n });
this.$el.append(v.render().el);
}, this);