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);