Backbone.Collection "change" events
by Alexander Rydén
HTML
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.0/backbone-min.js"></script>
CSS
#points-view,
#feed-view {
padding: 10px;
border: 1px solid #eee;
list-style: none;
}
JavaScript
var Player = Backbone.Model.extend({});
var Players = Backbone.Collection.extend({
model: Player
});
var PointsView = Backbone.View.extend({
id: 'points-view',
events: {
'click button': 'buttonClicked'
},
initialize: function() {
this.render();
},
render: function() {
// render a button for each player
for (var i = 0; i < this.collection.length; i++) {
var player = this.collection.at(i);
$('<button type="button">')
.text(player.get('name'))
.data('index', i)
.appendTo(this.$el);
}
return this;
},
buttonClicked: function(e) {
// increase the score for the player
var index = $(e.currentTarget).data('index'),
player = this.collection.at(index);
player.set('points', player.get('points') + 1);
}
});
var FeedView = Backbone.View.extend({
id: 'feed-view',
tagName: 'ul',
initialize: function() {
this.listenTo(this.collection, 'change', this.playerChanged);
},
playerChanged: function(player) {
var changedAttrs = player.changedAttributes();
if (changedAttrs && !_.isUndefined(changedAttrs.points)) {
// if the points attribute has changed, create a new feed item
var html = [
'<strong>',
player.get('name'),
'</strong> has scored <strong>',
player.get('points') - player.previous('points'),
'</strong> point(s)'
];
$('<li>')
.html(html.join(''))
.prependTo(this.$el);
}
}
});
var players = new Players([
{ name: 'kevin', points: 0 },
{ name: 'mike', points: 0 },
{ name: 'luke', points: 0 }
]);
$(document.body)
.append((new PointsView({ collection: players })).$el)
.append((new FeedView({ collection: players })).$el);