Backbone Collection Decorators

filtering, sorting and other decorators are easy to do with backbone collections.

by derickbailey

HTML

<script src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
<script src="http://documentcloud.github.com/backbone/backbone-min.js"></script>
<label>filter: <input id="filter"></label>
<div id="output"></div>
<p>&nbsp;</p>
<p>
    Type in to the text box. enter one of the items: "bar", "baz", "quux" and then tab out of the text box. It will filter to show only the items with that name. Empty the filter input and tab out again, to see the full list.
</p>

JavaScript

// Collection Decorator For Filtering
// ----------------------------------

function FilteredCollection(original){
    var filtered = new original.constructor();
    
    // allow this object to have it's own events
    filtered._callbacks = {};

    // call 'where' on the original function so that
    // filtering will happen from the complete collection
    filtered.where = function(criteria){
        var items;
        
        // call 'where' if we have criteria
        // or just get all the models if we don't
        if (criteria){
            items = original.where(criteria);
        } else {
            items = original.models;
        }
        
        // store current criteria
        filtered._currentCriteria = criteria;
        
        // reset the filtered collection with the new items
        filtered.reset(items);
    };
        
    
    // when the original collection is reset,
    // the filtered collection will re-filter itself
    // and end up with the new filtered result set
    original.on("reset", function(){
        filtered.where(filtered._currentCriteria);
    });
        
    return filtered;
}

// View To Filter Items
// --------------------

var view = Backbone.View.extend({
    initialize: function(){
        this.collection.on("reset", this.render, this);
    },
    
    render: function(){
        var result = this.collection.map(function(item){ 
            return item.get("foo"); 
        });
        this.$el.html(result.join(","));
    }
});


// Init A Collection And Decorate It
var stuff = new Backbone.Collection();
var filtered = FilteredCollection(stuff);


// Get A View To Show The Data
new view({
    el: $("#output"),
    collection: filtered
});


// Init And Run The App
$("#filter").change(function(e){
    var val = $(e.currentTarget).val();
    if (val){
        filtered.where({foo: val});
    } else {
        filtered.where();
    }
});


// Reset The Original Collection
stuff.reset([
    {foo: "bar"},
    {foo:...