最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to pluck multiple attributes from a Backbone collection? - Stack Overflow

programmeradmin5浏览0评论

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?

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?

Share Improve this question edited Sep 8, 2013 at 9:17 nikoshr 33.3k34 gold badges94 silver badges109 bronze badges asked Jun 15, 2013 at 7:38 kongarajukongaraju 9,59611 gold badges57 silver badges78 bronze badges 1
  • A jsFiddle example would be nice. – elclanrs Commented Jun 15, 2013 at 7:44
Add a comment  | 

3 Answers 3

Reset to default 17

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/

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"]

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']
发布评论

评论列表(0)

  1. 暂无评论