38

Is there a way to easily clone Backbone Collection? I wonder why there is no build in method like for models. My problem is that I have a model holding a collection of childs. When I clone the model. I've still the collection of childs but only with their default values.

Andreas Köberle
  • 106,652
  • 57
  • 273
  • 297

4 Answers4

60

Simplest way:

var cloned = new Backbone.Collection(original.toJSON());

where original is the collection to clone.

Could always then extend Backbone's Collection to add clone support w or w/o inheritance support.

chikamichi
  • 2,199
  • 1
  • 24
  • 16
  • 2
    This is a great answer because it will perform a deep clone, meaning it will clone the models as well. If you prefer a shallow clone where a new collection will point to the same model instances then use Craig Myles' answer below. – Dre Sep 10 '15 at 23:21
14

What's your use case that you want to clone the collection?

There isn't a built in clone function for a collection because you do not want to clone the models within the collection. Cloning a model would cause there to be two separate instances of the same model, and if you update one model, the other one won't be updated.

If you want to create a new collection based upon a certain criteria, then you can use the collection's filter method.

var freshmenModels = studentsCollection.filter(function(student) {
  return student.get('Year') === 'Freshman';
}

var freshmenCollection = new Backbone.Collection(freshmenModels);

To go ahead and clone the models in the collection, you can write the following code

var clonedCollection = new Backbone.Collection();
studentsCollection.each(function(studentModel) {
  clonedCollection.add(new Backbone.Model(studentModel.toJSON()));
});
Paul
  • 18,349
  • 7
  • 49
  • 56
  • 1
    But I want copy all single models in the collection. – Andreas Köberle Dec 21 '11 at 22:30
  • What are you trying to do that you need to copy/clone all the models in a collection? – Paul Dec 22 '11 at 00:20
  • I've bunch of products, which can have a list of sub products. So when some puts them in the basket I've to copy all sub products. The user can change the count of the product itself and for the sub products. So I need a copy of the original in the basket. – Andreas Köberle Dec 22 '11 at 08:07
  • @AndreasKöberle I updated my answer to show how to clone the models into a new collection. – Paul Dec 22 '11 at 16:17
  • This answer was useful to me because I'm modifying a collection by unsetting a bunch of unneeded attributes on a copy, but I don't want to affect the original collection. – mooreds Mar 29 '13 at 20:17
10

Use the Backbone Collection clone() method:

var clonedCollection = myCollection.clone();
Craig Myles
  • 5,206
  • 3
  • 40
  • 37
5

Another option, if you need the following (which is what I was looking for when I found this question ;) ):

  • The copy of the collection should be of the same type as the original collection (e.g. you've created your own collection type that extends Backbone.Collection)
  • The copy of the collection should be created with the same options as the original
  • The models in the copy of the collection should be created using the model.clone() method

Code:

var models = original.map(function (model) { return model.clone(); });    
var options = _.clone(original.options);    
var copy = new original.constructor(models, options);

A generic clone method on Backbone.Collection would be awkward because there are always going to be subtleties around whether models and their nested objects get copied by reference or are themselves cloned. Requirements will vary wildly according to your scenario, so it's been left for you to write what you need.

Dan Malcolm
  • 4,382
  • 2
  • 33
  • 27