18

I understand that using pluck method we can get an array of attributes of each model inside a backbone collection

var idsInCollection = collection.pluck('id'); // outputs ["id1","id2"...]

I want to if there is a method that sets up an attribute to each model in the collection,

var urlArray = ["https://url1", "https://url1" ...];
collection.WHAT_IS_THIS_METHOD({"urls": urlArray});
sublime
  • 4,013
  • 9
  • 53
  • 92

5 Answers5

39

There's not exactly a pre-existing method, but invoke let's you do something similar in a single line:

collection.invoke('set', {"urls": urlArray});

If you wanted to make a re-usable set method on all of your collections, you could do the following:

var YourCollection = Backbone.Collection.extend({
    set: function(attributes) {
        this.invoke('set', attributes);
        // NOTE: This would need to get a little more complex to support the
        //       set(key, value) syntax
    }
});

* EDIT *

Backbone has since added its own set method, and if you overwrite it you'll completely break your Collection. Therefore the above example should really be renamed to setModelAttributes, or anything else which isn't set.

machineghost
  • 33,529
  • 30
  • 159
  • 234
9

I don’t there is a method for it, but you can try:

collection.forEach(function(model, index) {
    model.set(url, urlArray[index]);
});
David Hellsing
  • 106,495
  • 44
  • 176
  • 212
  • Oh ya, that is how I'm doing it right now. I just wanted to know if there is a better way of doing it. – sublime Dec 14 '12 at 22:33
  • I would say use `each` (underscore) instead of `forEach` (native). `forEach` is not cross-browser compatible. – anushr Dec 16 '12 at 07:26
  • 4
    @anushr David is actually referencing the Underscore method here, not the native method. Backbone Collections proxy Underscore methods: http://backbonejs.org/#Collection-Underscore-Methods – Russ Dec 17 '12 at 07:09
  • @Russ my mistake, thanks for pointing it out. I keep forgetting about the `forEach` helper in underscore. – anushr Dec 18 '12 at 02:46
0

Expanding on David's answer, you can easily put this functionality into a custom method on the collection. Here's my way of doing it using coffeescript:

class Collection extends Backbone.Collection
  setAll: () ->
    _args = arguments
    @models.forEach (model) -> model.set _args...

class SomeCollection extends Collection
  url: '/some-endpoint.json'

myLovelyCollection = new SomeCollection()
myLovelyCollection.fetch
  success: (collection, response) ->
    collection.setAll someVar: true
    collection.setAll anotherVar, 'test'

If you wanted to do it in vanilla JS it's exactly the same but not harnessing the power of classes or splats. So more like:

var Collection = Backbone.Collection.extend({
  setAll: function () {
    var _args = arguments;
    this.models.forEach(function (model) {
      model.set.apply(model, _args);
    });
  }
});
Matt Fletcher
  • 8,182
  • 8
  • 41
  • 60
0

Just thought I'd post my slightly updated method based on machineghost's version. This uses lodash invokeMap method instead of underscore's invoke. It supports the same optional syntax as the standard model.set method ... e.g. ('prop', 'val') or ({prop: 'val', prop: 'val'}) as well accepting and passing an options object.

var YourCollection = Backbone.Collection.extend({
    setModels: function(key, val, options) {
        var attrs;

        if (typeof key === 'object') {
            attrs = key;
            options = val;
        } else {
            (attrs = {})[key] = val;
        }

        if (attrs) {
            _.invokeMap(this, 'set', attrs, options);
        }

        return this;
    }
});
relic
  • 1,662
  • 1
  • 16
  • 24
-3

If you are using invoke the syntax according to the underscore site should be _.invoke(list, methodName, *arguments) http://underscorejs.org/#invoke

So the above function mentioned by machineghost should be

collection.invoke({'url': someURL},'set');

Hope that helps :)

Community
  • 1
  • 1
  • 3
    This is wrong. `_.invoke(collection, methodName, arguments)` translates to `collection.invoke(methodName, arguments)` – Backbone or Underscore never flips the order of arguments --> `collection.invoke('set', { url: someUrl })` – Hein Haraldson Berg Sep 08 '14 at 08:04