我有一个与自己相关的hasMany
和belongsTo
模型
Todos.Todo = DS.Model.extend({
title: DS.attr('string'),
isCompleted: DS.attr('boolean'),
parent: DS.belongsTo('todo', {inverse: 'children'}),
children: DS.hasMany('todo', {inverse: 'parent'})
});
我将让用户相互拖放todos让他重新排列层次结构。但对于一个不熟悉Ember的人来说,这是一项艰巨的任务,所以我决定从更简单的事情开始:
每个待办事项都包含可能的父母的下拉列表。用户可以从列表中选择任何父级,并使用该父级更新待办事项。
下拉列表中还有一个“无父”项。当为待办事项选择它时,此待办事项将更新为不包含父项。
我执行修改todo父级的方式非常简单:
controllers.todos.model
)中获取一组模型。parent
字段设置为抓取的记录对象。我还在todo控制器上创建了几个简单的属性,以查看每个待办事项是否有父母和孩子:
hasChildren: (function() {
return this.get('model.children').get('length') > 0;
}).property('model.parent', 'model.children'),
hasParent: (function() {
return this.get('model.parent') !== null;
}).property('model.parent', 'model.children'),
从hasParent
属性我可以看出,当我使用下拉列表更改todo的父级时,父级会被修改,是的!修改通过页面刷新(我正在使用本地存储适配器)持续存在,所以我假设我正确地执行更新todo的父级。
问题是当我更新todo A上的'parent'属性以包含待办事项B时,todo B上的hasChildren
属性没有被更新。这使我无法自动刷新页面上的待办事项层次结构。
我曾经认为,当我更新孩子的children
属性时,Ember Data会自动更新父级的parent
属性。那就是inverse
的东西,对吗?如果Ember Data不能自动维护关系的完整性,为什么要知道关系的相反属性?
所以要么我错了,我应该在更新子todo上的children
属性时手动更新旧父母和新父母的parent
属性(冒着破坏关系完整性的危险) ,或者我正以错误的方式改变父母。
问题是:在hasMany / belongsTo关系中更改项目所有权的正确方法是什么?
小提琴:http://jsbin.com/UDoPajA/220/edit
我已经尝试过你的方法并没有任何区别。 :(我已经应用了您的建议,并且模型hasParent
属性确实会动态更新。但haschildren
属性没有。
但后来我尝试设置hasChildren
属性来观察todos.@each.parent
并且它开始更新了,是的!
我仍然不明白:为了改变记录的关系,我必须做很多工作。这就是我如何应用你的建议:
var model = this.get('model');
// Removing current todo from the list of children of the former parent
model
.get('parent')
.get('children')
.removeObject(model);
// Adding current todo to the list of children of the new parent
this
.get('todos')
.filter( function(candidateTodo) {
return candidateTodo.get('id') === newParentId;
})[0]
.pushObject(model);
model.save();
这是一项很多工作,也更容易打破关系的完整性。为什么我不能这样做呢?
var model = this.get('model');
var newParent = this
.get('todos')
.filter( function(candidateTodo) {
return candidateTodo.get('id') === newParentId;
})[0];
model.set('parent', newParent);
model.save();
我已经尝试过了,但它不起作用。 :(父属性更新,但子属性不会。
有没有办法从belognsTo
端正确更新关系,而不是做额外的工作来更新hasMany
端的关系。
我发现this answer但它基本上意味着两端的手动更新,我也不喜欢它。提问者也惊讶于Ember需要手动完成。
有一个更奇怪的事情。为了更新当前模型的parent
属性,我们必须修改另一端的关系(在父项的children
属性上调用方法)。如果我们在父项上执行此操作,为什么需要在当前模型上执行.save()
而不是父模型才能保持更改?为什么hasChildren
属性必须遵守todos.@each.parent
并且观察model.children
不起作用?
还有另一个未解决的问题:当添加新的待办事项或删除现有的待办事项时,所有待办事项的“父:”下拉列表将重置为“无父”状态!但是,如果我刷新页面,则会恢复下拉列表中正确的父选择。 Whaaat?
请帮我解决这些问题。小提琴:http://jsbin.com/UDoPajA/231/edit
答案 0 :(得分:2)
如果设置inverse
属性,则只需要从关系中推送/删除对象,而ember-data将注意更新依赖关系。
parent.get('children').then(function(children){
children.removeObject(child);
})
parent.get('children').then(function(children){
children.pushObject(child);
})
由于ember-data的当前状态(使用v1.0.0-beta.8),您可以将hasParent
和hasChildren
定义为:
hasChildren: Ember.computed.notEmpty('children.[]'),
hasParent: Ember.computed.notEmpty('parent.content')