user1031947
user1031947

Reputation: 6664

How to clone models from Backbone collection to another

I need to clone the models in one backbone collection and add then add them to another. (IOW all of the models in the new collection need to be unique, and have no connection to the models in the original collection.)

Here is my code:

collection1.each(function( model ) {
  var clone = new Backbone.Model( model.toJSON() );
  clone.set( this.idAttribute, null, { silent: true });
  collection2.add( clone );
});

This doesn't quite work. I can only add a model from collection1 to collection2 once. If I try to do it a second time, it fails. So somehow Backbone is detecting a dup.

Any suggestions on what I am doing wrong?

Thanks (in advance) for your help

Upvotes: 3

Views: 3285

Answers (2)

Damien
Damien

Reputation: 664

That's an old question, but @nikoshr and this answers helped me so I'd like to add my contribution.

In my case I needed to clone a model including nested collections :

app.Collections.collection1 = Backbone.Collection.extend({
    model: app.Models.model1,
    clone: function() {
        return new this.constructor(_.map(this.models, function(model) { var clone = model.clone().unset('id', {silent: true}).unset('idAttribute', {silent: true}); return clone.set('collection2', clone.get('collection2').clone()); }));
    }
});

app.Collections.collection2 = Backbone.Collection.extend({
    model: app.Models.model2,
    clone: function() {
        return new this.constructor(_.map(this.models, function(model) { return model.clone().unset('id', {silent: true}).unset('idAttribute', {silent: true}); }));
    }
});

    var clone = this.model.clone().unset('id', {silent: true}).unset('idAttribute', {silent: true});
    clone.set('collection1', clone.get('collection1').clone());
    var copy = this.model.collection.add(clone, {parse: true});

So in your case I guess you could do something like that :

app.Collections.collection1 = Backbone.Collection.extend({
    clone: function() {
        return new this.constructor(_.map(this.models, function(model) { return model.clone().unset('idAttribute', {silent: true}); }));
    }
});

collection2.add(collection1.clone().models);

Upvotes: 0

nikoshr
nikoshr

Reputation: 33344

In the code you provided, this.idAttribute is probably not what you think it is and thus won't create models without their ids, leading to collisions when you copy the models a second time.

Underscore is a hard dependency of Backbone, so you can use _.omit on the JSON representation of your collection to filter out the ids. For example,

function copyCollection(collection1, collection2){
    var idAttribute = collection1.model.prototype.idAttribute;

    var data = _.map(
        collection1.toJSON(), 
        function(obj){ return _.omit(obj, idAttribute); }
    );

    collection2.add(data);
}

var c1 = new Backbone.Collection([
    {id: 1, name: "N1"},
    {id: 2, name: "N2"}
]);
var c2 = new Backbone.Collection();

copyCollection(c1, c2);
copyCollection(c1, c2);
console.log(c2.toJSON());

And a Fiddle http://jsfiddle.net/jT59v/

Upvotes: 1

Related Questions