43

I have a defined model and a collection:

var Box = Backbone.Model.extend({
    defaults: {
        x: 0,
        y: 0,
        w: 1,
        h: 1,
        color: "black"
    }

});

var Boxes = Backbone.Collection.extend({
    model: Box
});

When the collection is populated with the models, I need a new Boxes collection made out of Box models that have a specific color attribute contained in the complete collection, I do it this way:

var sorted = boxes.groupBy(function(box) {
    return box.get("color");
});


var red_boxes = _.first(_.values(_.pick(sorted, "red")));

var red_collection = new Boxes;

red_boxes.each(function(box){
    red_collection.add(box);
});

console.log(red_collection);

This works, but I find it a bit complicated and unefficient. Is there a way of doing this same thing in a more simple way?

Here is the code I described: http://jsfiddle.net/HB88W/1/

alex
  • 479,566
  • 201
  • 878
  • 984
rpabon
  • 1,191
  • 2
  • 16
  • 22

2 Answers2

83

I like returning a new instance of the collection. This makes these filtering methods chainable (boxes.byColor("red").bySize("L"), for example).

var Boxes = Backbone.Collection.extend({
    model: Box,

    byColor: function (color) {
        filtered = this.filter(function (box) {
            return box.get("color") === color;
        });
        return new Boxes(filtered);
    }
});

var red_boxes = boxes.byColor("red")
Eliran Malka
  • 15,821
  • 6
  • 77
  • 100
hgmnz
  • 13,208
  • 4
  • 37
  • 41
  • 3
    Will this change cid in model? – janetsmith Mar 11 '13 at 13:30
  • 4
    filterBy: function(attribute, value) { filtered = this.filter(function(box) { return box.get(attribute) === value; }); return new Boxes(filtered); } – Joshua Jul 07 '13 at 15:27
  • Why return a `new Boxes()`. I would write var Boxes = Backbone.Collection.extend({ model: Box, byColor: function(color) { return this.filter(function(box) { return box.get("color") === color; }); } }); – marcoslhc Oct 09 '13 at 20:03
  • 2
    Is this using filter from Underscore.js? – paniclater May 23 '14 at 19:39
  • 5
    Marcoslhc: that won't return a Backbone collection but an array of models – Phortuin Jul 28 '14 at 09:42
  • Adding two related and interesting links: http://tech.pro/tutorial/1519/rendering-a-filtered-backbonecollection https://github.com/p3drosola/Backbone.VirtualCollection – enricostn Sep 26 '14 at 22:21
  • @janetsmith No, it won't change the cid of the model. That would only happen if you initialized a new one or cloned it. – Joshua Feb 21 '15 at 19:31
  • 4
    you may want to declare the `filtered` variable in its scope (`byColor` function) – Eliran Malka Jun 09 '15 at 14:50
  • 1
    @paniclater I would assume so since Backbone is based on Underscore. – NoBugs Sep 01 '15 at 05:00
48

See http://backbonejs.org/#Collection-where

var red_boxes = boxes.where({color: "red"});

var red_collection = new Boxes(red_boxes);
Andrei
  • 10,918
  • 12
  • 76
  • 110