tot*_*hda 8 relationships ember.js ember-data
我有两个有亲子关系的模型:训练和锻炼:
App.Training = DS.Model.extend({
exercises: DS.hasMany('App.Exercise')
})
App.Exercise = DS.Model.extend({
training: DS.belongsTo('App.Training')
})
Run Code Online (Sandbox Code Playgroud)
我希望有一个页面,其中显示了所有相关练习的训练.如果用户按下Edit按钮,则页面变得可编辑,可以添加新练习.我还想要一个Cancel放弃所有更改的按钮.
这是我的控制器:
App.TrainingsShowController = Em.ObjectController.extend({
editing: false,
edit: function() {
this.set('editing', true);
transaction = this.get('store').transaction();
transaction.add(this.get('model'));
this.get('model.exercises').forEach(function(x){
transaction.add(x);
});
},
cancel: function() {
this.set('editing', false);
this.get('model.transaction').rollback();
},
save: function() {
this.set('editing', false);
this.get('model.transaction').commit();
},
addExercise: function() {
this.get('model.exercises').createRecord({});
}
})
Run Code Online (Sandbox Code Playgroud)
控制器中有四个事件处理程序:
edit:用户按下Edit按钮:创建事务,页面进入"编辑"模式.cancel:用户按下Cancel按钮:事务回滚并返回"正常"模式.save:用户按下Save按钮:提交事务并返回"正常"模式.addExercise:用户按下Add exercise按钮:创建新练习(在同一事务中)并添加到培训中.除了新创建的记录之外,回滚功能正常工作:如果我按下Edit按钮,添加新练习并按下Cancel按钮,新创建的练习将保留在页面上.
什么是摆脱丢弃的儿童记录的最佳方法?
更新:
我已经创建了一个jsFiddle来重现问题,但它确实有效.与我在这里使用的应用程序不同DS.FixtureAdapter:http://jsfiddle.net/tothda/LaXLG/13/
然后我创建了另一个使用DS.RESTAdapter,问题出现了:http://jsfiddle.net/tothda/qwZc4/5/
在小提琴尝试:编辑,添加新,然后回滚.
我想通了,在RESTAdapter的情况下,当我向hasMany关系添加新的子记录时,父记录不会变脏.这看起来很好,但是当我回滚事务时,新创建的子记录保留在父项中ManyArray.
我还是不知道,处理这种情况的最佳方法是什么.
Joh*_*ika 11
在Ember Data中,hasMany和belongsTo关系的正确脏检查和回滚非常缺乏.它目前的行为方式通常被报告为错误.对于很多开发人员来说,这是一个很大的痛点,目前正在讨论如何解决这个问题:
https://github.com/emberjs/rfcs/pull/21
在有适当的解决方案之前,您可以使用以下方法解决此问题.
首先,您需要重新打开DS.Model并对其进行扩展.如果你正在使用全局变量,你可以把它(例如DS.Model.reopen({}))放在任何地方,但是如果你使用Ember CLI,最好创建一个初始化器(例如ember g初始化器模型):
import DS from 'ember-data';
export function initialize(/* container, application */) {
DS.Model.reopen({
saveOriginalRelations: function() {
this.originalRelations = {};
this.constructor.eachRelationship(function(key, relationship) {
if (relationship.kind === 'belongsTo')
this.originalRelations[key] = this.get(key);
if (relationship.kind === 'hasMany')
this.originalRelations[key] = this.get(key).toArray();
}, this);
},
onLoad: function() {
this.saveOriginalRelations();
}.on('didLoad', 'didCreate', 'didUpdate'),
onReloading: function() {
if (!this.get('isReloading'))
this.saveOriginalRelations();
}.observes('isReloading'),
rollback: function() {
this._super();
if (!this.originalRelations)
return;
Ember.keys(this.originalRelations).forEach(function(key) {
// careful, as Ember.typeOf for ArrayProxy is 'instance'
if (Ember.isArray(this.get(key))) {
this.get(key).setObjects(this.originalRelations[key]);
this.get(key).filterBy('isDirty').invoke('rollback');
return;
}
if (Ember.typeOf(this.get(key)) === 'instance') {
this.set(key, this.originalRelations[key]);
return;
}
}, this);
},
isDeepDirty: function() {
if (this._super('isDirty'))
return true;
if (!this.originalRelations)
return false;
return Ember.keys(this.originalRelations).any(function(key) {
if (Ember.isArray(this.get(key))) {
if (this.get(key).anyBy('isDirty'))
return true;
if (this.get(key).get('length') !== this.originalRelations[key].length)
return true;
var dirty = false;
this.get(key).forEach(function(item, index) {
if (item.get('id') !== this.originalRelations[key][index].get('id'))
dirty = true;
}, this);
return dirty;
}
return this.get(key).get('isDirty') || this.get(key).get('id') !== this.originalRelations[key].get('id');
}, this);
}
});
};
export default {
name: 'model',
initialize: initialize
};
Run Code Online (Sandbox Code Playgroud)
上面的代码基本上存储了加载或更新时的原始关系,以便以后可以用于回滚和脏检查.
model.rollback()现在应该回滚所有内容,包括hasMany和belongsTo关系.我们仍然没有完全解决'isDirty'检查.为此,我们需要在模型的具体实现中覆盖isDirty.我们之所以需要在此处执行此操作并且我们无法在DS.Model中进行一般操作,是因为DS.Model不知道要监视的属性更改.这是使用Ember CLI的示例.除了你将这个类分配给像App.Book这样的类之外,同样的方法将用于全局变量:
import DS from 'ember-data';
var Book = DS.Model.extend({
publisher: DS.belongsTo('publisher'),
authors: DS.hasMany('author'),
isDirty: function() {
return this.isDeepDirty();
}.property('currentState', 'publisher', 'authors.[]', 'authors.@each.isDirty').readOnly()
});
export default Book;
Run Code Online (Sandbox Code Playgroud)
对于isDirty的依赖参数,请确保包含所有belongsTo关系,并且还为每个hasMany关系包含'array.[]'和'array.@ each.isDirty'.现在isDirty应该按预期工作.
这不太漂亮,但您可以通过手动弄脏父记录来强制它回滚:
parent.send('becomeDirty');
parent.rollback();
parent.get('children.length'); // => 0
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4100 次 |
| 最近记录: |