Skip to content

Instantly share code, notes, and snippets.

@coodoo
Created December 1, 2012 08:15
Show Gist options
  • Save coodoo/4181074 to your computer and use it in GitHub Desktop.
Save coodoo/4181074 to your computer and use it in GitHub Desktop.
Backbone Collection View
/**
* Backbone Collection View
*
* A light-weight approach to display filetered data from collection by assigning rules, without changing original models,
* which works just like CollectionView in other languages (ie: Java, WPF and AS3).
*
* Usage:
*
* 1. Filter by single field:
* this.wineList.filterView( {Country:'France'}} );
*
* 2. Filter by any field with the value
* this.wineList.filterView( obj, {matchAny:true} );
*
* 3. Clearn filter
* this.wineList.filterView( null );
*
* @author Jeremy Lu ([email protected])
*/
/**
* keep a copy of original models
*/
Backbone.Collection.prototype.originalModels = null;
/**
* @param ruleObj as in _.filter({prop:value})
* @param optionsObj {matchAny:true} search all properties in model to find a match
*/
Backbone.Collection.prototype.filterView = function( ruleObj, optionsObj ){
//restore original value before each search
this.resetFilterView();
//if ruleObj is null, stop here, the model will be reset
if( ruleObj === null ){
this.trigger( 'refresh' );
return;
}
//debug
// this.originalModels;
var newModels;
//match any
if( optionsObj && optionsObj.matchAny == true )
{
var searchValue = ruleObj.all;
newModels = _.filter( this.models, function( item){
var t = _.contains( item.attributes, searchValue );
// console.log( "t = ", t );
return t;
});
}
else
{
//find match items
newModels = this.where( ruleObj );
}
//update filtered models
this.models = newModels !== null ? newModels : [];
//dispatch refresh event so view can update itself accordingly
this.trigger( 'refresh' );
}
/**
* restore original models value
*/
Backbone.Collection.prototype.resetFilterView = function(){
if( this.originalModels !== null ){
this.models = this.originalModels;
}
else
{
this.originalModels = this.models;
}
}
@smagch
Copy link

smagch commented Dec 10, 2012

You can do this.filter(function (item){}); instead of _.filter( this.models, function (item){}); since it's mixed in. I think tampering original .models is really bad idea. I'd send filtered models with triggering custom events in that case.

var MyCollection = Backbone.Collection.extend({
  filter: function(roleObj, options) {
    this.resetFilter();
    this._filtered = this.filter(function(item) {
      // some stuff
    });

    this.trigger('filter', this._filtered);
  },
  resetFilter: function() {
    if (this._filtered) {
      this.trigger('resetFilter', this._filtered);
      this._filtered = null;
    }
  }
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment