【发布时间】:2014-06-02 06:21:12
【问题描述】:
我有一个模型,它与自身相关的 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'})
});
我打算让用户在彼此上拖放待办事项,让他重新排列层次结构。但这对于不熟悉 Ember 的人来说是一项艰巨的任务,所以我决定从更简单的开始:
每个待办事项都包含一个可能父母的下拉列表。用户可以从列表中选择任何父级,待办事项会随该父级更新。
下拉列表中还有一个“无父”项。当为 todo 选择它时,此 todo 将更新为不包含父项。
我对 todo 的父项进行修改的方式非常简单:
- 从 Todos ArrayController (
controllers.todos.model) 获取模型集合。 - 过滤集合,使其仅包含 id 等于请求 id 的记录(来自用户在下拉列表中的选择)。
- 从过滤后的集合中获取第一条也是唯一一条记录。
- 将当前记录的
parent字段`设置为抓取的记录对象。 - 保存当前记录。
我还在 todo 控制器上创建了几个简单的属性来查看每个 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 的父项。
问题是当我更新待办事项 A 上的“父”属性以包含待办事项 B 时,待办事项 B 上的 hasChildren 属性未更新。这使我无法自动刷新页面上待办事项的层次结构。
我曾经认为当我更新子级的parent 属性时,Ember Data 应该自动更新父级的children 属性。这就是inverse 的用途,对吧?如果 Ember Data 不应该自动维护关系的完整性,它为什么要知道关系的相反属性?
所以要么我错了,当我更新子待办事项的parent 属性时,我应该手动更新新老父母的children 属性(有可能破坏关系的完整性),或者我' m 以错误的方式更改父级。
问题是:在 hasMany/belongsTo 关系中更改项目所有权的正确方法是什么?
小提琴:http://jsbin.com/UDoPajA/220/edit
用于 ppcano 的 UPD1:
我已经尝试过您的方法,但没有任何区别。 :( 我已经采纳了您的建议,并且模型 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不起作用?
还有另一个未解决的问题:当添加新的待办事项或删除现有的待办事项时,所有待办事项的“父项:”下拉列表将重置为“无父项”状态!但是如果我刷新页面,下拉列表中正确的父选择就会恢复。什么?
请帮我解决这些问题。小提琴:http://jsbin.com/UDoPajA/231/edit
【问题讨论】:
标签: ember.js