Reputation: 9586
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?
Upvotes: 9
Views: 8780
Reputation: 33334
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);
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);
Upvotes: 17
Reputation: 14501
http://jsfiddle.net/CoryDanielson/Lj3r85ew/
You could add select
methods to collections and models.
(or name it whatever you feel is appropriate)
/**
Backbone Model Select/Multi-get -------------------------------------------
*/
Backbone.Model.prototype.select = function(props) {
if ( arguments.length > 1 ) {
props = slice.call(arguments);
}
if ( _.isArray(arguments[0]) ) {
props = arguments[0];
}
// If requesting multiple, return all props
if ( _.isArray(props) ) {
return _.object(props, _.map(props, _.bind(this.get, this)));
}
// Else, return single property
return this.get(props);
}
/**
Backbone Collection Select ------------------------------------------------
*/
Backbone.Collection.prototype.select = function(props) {
if ( arguments.length > 1 ) {
props = slice.call(arguments);
}
if ( _.isArray(arguments[0]) ) {
props = arguments[0];
}
return _.map(this.models, function(m) {
return m.select(props);
});
}
This would allow you to select multiple properties across all models of a collection, or select multiple properties on a model.
collection.select('id', 'first', 'last'); // or ['id', 'first', 'last']
model.select('first', 'last'); // or ['first', 'last']
Upvotes: 0
Reputation: 94101
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"]
Upvotes: 3