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)
.
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);
});
},
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)
});
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.
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();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With