Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Marionette.js CollectionView, only render specific models

I am refactoring my Backbone.js application to use Marionette.js, and I am trying to wrap my head around a CollectionView.

Suppose I have several ItemViews with the model Cow:

// Declare my models.
var Cow = Backbone.Model.extend({});
var Cows = Backbone.Collection.extend({
  model: Cow
});

// Make my views
var GrassPatch = Marionette.ItemView.extend({
  tagName:  'div',
  template: "<section class='grass'>{{name}}</section>",
})

var Pasture = Marionette.CollectionView.extend({});

// Instantiate the CollectionView,
var blissLand = new Pasture({
  itemView: GrassPatch;
});

// Now, add models to the collection.
Cows.add({
  name: 'Bessie',
  hasSpots: true
});

Cows.add({
  name: 'Frank',
  hasSpots: false
});

Now here's the trick. I only want cows with spots in my pasture. How, in defining my CollectionView (Pasture), do I tell it to only pay attention to those models whose hasSpots === true?

Ideally I would like to have the CollectionView filter that in all events, but minimally, how do I only render some ItemViews based on their model properties?

UPDATE

I used David Sulc's examples and this worked out to an easy solution. Here's an example implementation:

  this.collection = Backbone.filterCollection(this.collection, function(criterion){
    var len = String(criterion).length;
    var a = criterion.toLowerCase();
    return function(model){
      var b = String(model.get('name')).substr(0, len).toLowerCase();
      if (a === b) {
        return model;
      }
    };
  });

  this.collection.add({ name: 'foo' });
  this.collection.add({ name: 'foosball' });
  this.collection.add({ name: 'foo bar' });
  this.collection.add({ name: 'goats' });
  this.collection.add({ name: 'cows' });

  this.collection.filter('foo');

  // -> returns the first three models
like image 753
dthree Avatar asked Sep 04 '13 01:09

dthree


1 Answers

Marionette handles this for you in v2.4.1.

See the CollectionView.filter method.

Following is from the docs:

  var cv = new Marionette.CollectionView({
    childView: SomeChildView,
    emptyView: SomeEmptyView,
    collection: new Backbone.Collection([
      { value: 1 },
      { value: 2 },
      { value: 3 },
      { value: 4 }
    ]),

    // Only show views with even values
    filter: function (child, index, collection) {
      return child.get('value') % 2 === 0;
    }
  });

  // renders the views with values '2' and '4'
  cv.render();

  // change the filter
  cv.filter = function (child, index, collection) {
    return child.get('value') % 2 !== 0;
  };

  // renders the views with values '1' and '3'
  cv.render();

  // remove the filter
  // note that using `delete cv.filter` will cause the prototype's filter to be used
  // which may be undesirable
  cv.filter = null;

  // renders all views
  cv.render();
like image 108
Jeff Avatar answered Oct 19 '22 22:10

Jeff