Skip to content

Instantly share code, notes, and snippets.

@danmartens
Last active December 11, 2015 02:28
Show Gist options
  • Save danmartens/4530689 to your computer and use it in GitHub Desktop.
Save danmartens/4530689 to your computer and use it in GitHub Desktop.
A Backbone.View for displaying a Backbone.Collection.
/*
* Example:
*
* ListView = Backbone.CollectionView.extend({
* tagName: 'ul'
* itemView: Backbone.View.extend({
* tagName: 'li',
* template: _.template('<%= item.content %>'),
*
* initialize: function() {
* this.render();
* },
*
* render: function() {
* this.$el.html(this.template({ item: this.model.toJSON() }));
* return this;
* }
* })
* });
*
* $('body').html( (new ListView({ collection: App.data.items })).render().el );
*/
(function() {
Backbone.CollectionView = Backbone.View.extend();
_.extend(Backbone.CollectionView.prototype, {
_configure: function(options) {
Backbone.View.prototype._configure.apply(this, arguments);
this._itemViewIndex = {};
},
delegateEvents: function() {
var _self = this;
Backbone.View.prototype.delegateEvents.apply(this, arguments);
if (this.collection) {
this.listenTo(this.collection, 'add', function(model) {
_self.renderItem(model);
});
this.listenTo(this.collection, 'remove', function(model) {
_self.removeItem(model);
});
this.listenTo(this.collection, 'reset', function() {
_self.renderAllItems();
});
this.listenTo(this.collection, 'sort', function() {
_self.reorderItems();
});
}
},
undelegateEvents: function() {
Backbone.View.prototype.undelegateEvents.apply(this, arguments);
if (this.collection) {
this.stopListening(this.collection);
}
},
render: function() {
if (this.collection) {
this.renderAllItems();
}
return this;
},
renderItem: function(model) {
var view = new this.itemView({ model: model });
var index = this.collection.indexOf(model);
view.collectionView = this;
view.render();
this._itemViewIndex[model.cid] = view;
if (index === 0) {
this.$el.prepend(view.el);
} else {
this._itemViewIndex[this.collection.at(index - 1).cid].$el.after(view.el);
}
},
renderAllItems: function() {
var _self = this;
this.removeAllItems();
this.collection.each(function(model) {
_self.renderItem(model);
});
},
removeItem: function(model) {
var view = this._itemViewIndex[model.cid];
if (view) {
view.remove();
delete this._itemViewIndex[model.cid];
}
},
removeAllItems: function() {
var _self = this;
_.each(this._itemViewIndex, function(view) {
view.remove();
});
this._itemViewIndex = {};
},
reorderItems: function() {
var _self = this;
this.collection.each(function(model) {
_self.$el.append(_self._itemViewIndex[model.cid].el);
});
}
});
}).call(this);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment