Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ember.js Clone an existing record into the store

I am struggling with the concept Ember.js will like. What I want is the following. I have now an existing Ember Data model called Article. Lets say with the id of 1 will be shown on /article/1.

When the user hit the New button they are transitioned to the 'article.new' route. See my routers:

App.Router.map(function () {
   this.resource('article', {path: '/article/:id'});
   this.resource('article.new', {path: "/article/new"});
}

When the user click the Duplicate button when they are at /article/1 the duplicateArticle action gets called. I intuitively do the following in App.ArticleController:

duplicateArticle: function () {
   return this.transitionToRoute('article.new', this.get('model');
}

However that is not going to work. I think because I need an path in my article.new route. However, when a user click on the New button I do not need an ID.

Is there a valid solution to this question?

Edit: My tries so far:

var currentArticle = this.get('model'); 
currentArticle.set('id', null); 
var duplicatedArticle = this.store.createRecord('article', currentArticle); 
duplicatedArticle.save();

and:

var duplicatedArticle = Ember.copy(this.get('model'), true);

and:

 var newArticle = JSON.parse(JSON.stringify(this.get('model')));
 var duplicatedArticle = this.store.createRecord('article', newArticle);
 duplicatedArticle.save();

The last try does work except for belongsTo and hasMany properties.

Is there no Ember way of doing this?

References:

Ember clone model for new record

Is there any way to convert Ember Object into plain javascript object?

Iterating over Ember.js ember-data Record Arrays

How can I clone an Ember Data record, including relationships? (not answered, 75% the same question as me)

.

Update: a simple example with also belongsTo items saved

hasMany does not work. Contribute to this answer if you have a solution!

My final solution without hasMany items is now as follows:

In my actions of my ArticleController:

  duplicateArticle: function () {
        var article = this.get('model').toJSON(),
            self = this;

        // todo implement saving hasMany items

        // set belongsTo items by hand
        article['landcode'] = this.get('landcode');
        article['employee'] = this.get('employee');
        article['cross_selling_article_relation'] = this.get('cross_selling_article_relation');

        var duplicatedArticle = this.store.createRecord('article', article);

        // save and transite to newly created article
        duplicatedArticle.save().then(function (savedArticle) {
            self.transitionToRoute('article', savedArticle.id);
        });
    },
like image 416
DelphiLynx Avatar asked Dec 09 '13 17:12

DelphiLynx


Video Answer


3 Answers

Now we have a add-on to copy models ember-cli-copyable

With this add on, just add the Copyable mix-in to the target model which is to be copied and use the copy method

Example from the add-on site

import Copyable from 'ember-cli-copyable';

Account = DS.Model.extend( Copyable, {
  name: DS.attr('string'),
  playlists: DS.hasMany('playList'),
  favoriteSong: DS.belongsTo('song')
});

PlayList = DS.Model.extend( Copyable, {
  name: DS.attr('string'),
  songs: DS.hasMany('song'),
});

//notice how Song does not extend Copyable 
Song = DS.Model.extend({
  name: DS.attr('string'),
  artist: DS.belongsTo('artist'),
});
//now the model can be copied as below
this.get('currentAccount.id') // => 1 
this.get('currentAccount.name') // => 'lazybensch' 
this.get('currentAccount.playlists.length') // => 5 
this.get('currentAccount.playlists.firstObject.id') // => 1 
this.get('currentAccount.favoriteSong.id') // => 1 

this.get('currentAccount').copy().then(function(copy) {

  copy.get('id') // => 2 (differs from currentAccount) 
  copy.get('name') // => 'lazybensch' 
  copy.get('playlists.length') // => 5 
  copy.get('playlists.firstObject.id') // => 6 (differs from currentAccount) 
  copy.get('favoriteSong.id') // => 1 (the same object as in currentAccount.favoriteSong) 

});
like image 197
Vinoth Kumar Avatar answered Sep 26 '22 20:09

Vinoth Kumar


Ember Data is in beta, so missing functionality is to be expected, relationships are only resolved from ids when resolved through find.

If you create a dummy id you can pushPayload then find.

W/o relationships, you can use record.toJSON() to get the attributes w/o id, then send it to createRecord.

http://emberjs.jsbin.com/OxIDiVU/13/edit

You should submit a PR with duplicate logic, it would be a great way to contribute to the community.

like image 27
Kingpin2k Avatar answered Sep 23 '22 20:09

Kingpin2k


I have a solution for copying/duplicating an Ember Data record, including its one-to-many relationships.

I have a "duplicate" method:

duplicate: function(oldObject) {
  var newObject = oldObject.toJSON();
  for (var key in newObject) {
    if (newObject[key] != oldObject.get(key)) {
        newObject[key] = oldObject.get(key);
    }
  }
  newObject.id = null;
  return newObject;
}

And I use this method in an action like this:

actions: {
  draft: function() {
    var newModel = this.duplicate(this.get('model'));
    this.store.createRecord('somemodel', newModel).save();
  }
}
like image 34
Ryan D Avatar answered Sep 25 '22 20:09

Ryan D