Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pluck multiple attributes from a Backbone collection?

I am trying to pluck multiple attributes from a Backbone collection but it returns undefined.

collection

{
    id:1,
    name:"raju",
    age:23,
    sex:male,
    hobbies:..
}
{
    id:2,
    name:"ramesh",
    age:43,
    sex:male,
    hobbies:..
}

... //many models

I am trying to get multiple attributes from collection.

collection.pluck(["id","name","age","sex"]);

Expected output

[{//multiple attributes},{}]

is there any alternative way to get multiple attributes?

like image 416
kongaraju Avatar asked Jun 15 '13 07:06

kongaraju


2 Answers

As @elclanrs said, collection.pluck extracts a single attribute, you will have to use _.map with a custom extraction function. Something like

var c = new Backbone.Collection([
    {id: 1, name: "raju", age: 23, sex: "male"},
    {id: 2, name: "ramesh", age: 43, sex: "male"}
]);

var plucked = c.map(function (model) {
    return _.pick(model.toJSON(), ["name", "age"]);
});
console.log(plucked);

And a demo http://jsfiddle.net/U7p9u/


You could simplify this call by combining Collection.invoke and Model.pick

var c = new Backbone.Collection([
    {id: 1, name: "raju", age: 23, sex: "male"},
    {id: 2, name: "ramesh", age: 43, sex: "male"}
]);

plucked = c.invoke("pick", ["name", "age"]);  
console.log(plucked);

http://jsfiddle.net/U7p9u/5/


In a similar spirit, if your extraction function is defined on the prototype of your models:

var M = Backbone.Model.extend({
    mypluck: function () {
        return this.pick("name", "age");
    }
});

var C = Backbone.Collection.extend({
    model: M
});

var c = new C([
    {id: 1, name: "raju", age: 23, sex: "male"},
    {id: 2, name: "ramesh", age: 43, sex: "male"}
]);

var plucked = c.invoke("mypluck");
console.log(plucked);

http://jsfiddle.net/U7p9u/3/

like image 136
nikoshr Avatar answered Oct 24 '22 23:10

nikoshr


In the docs it says:

"[pluck is the] Equivalent to calling map and returning a single attribute from the iterator."

This leads me to believe that it isn't possible with multiple properties because you're basically replacing one item in the collection with one of its properties. So basically you're doing this:

var collect = [{a:'foo',b:'baz'},{a:'lol',b:'fur'}];

var key = 'a';
var result = collect.map(function(o){ return o[key] });

A possible solution would be to return an array and then flatten it, something like this:

result = [].concat.apply([],collect.map(function(o){ return [o.a,o.b]; }));

console.log(result); //=> ["foo", "baz", "lol", "fur"]
like image 40
elclanrs Avatar answered Oct 25 '22 01:10

elclanrs