Javascript 学习Ember.js-多对多关系中的持久性
为了学习Ember.js,我开始编写一个小型书签应用程序。我现在正在努力解决与错误数据处理相关的问题 解释应用程序Javascript 学习Ember.js-多对多关系中的持久性,javascript,ember.js,ember-data,handlebars.js,Javascript,Ember.js,Ember Data,Handlebars.js,为了学习Ember.js,我开始编写一个小型书签应用程序。我现在正在努力解决与错误数据处理相关的问题 解释应用程序 用户可以添加标签 用户可以添加指向选定标签的链接 一个标签可以有n个链接 链接可以有n个标签 通过选择关联的标签显示链接 问题 链接数据未写入数据存储。因此,将覆盖由于选择更改而对链接模型的本地更新。而且,以后实现真正的持久性也不起作用 缩小问题范围 在IndexRoute中,我初始化模型: model: function(params) { return {
- 用户可以添加标签
- 用户可以添加指向选定标签的链接
- 一个标签可以有n个链接
- 链接可以有n个标签
- 通过选择关联的标签显示链接
链接数据未写入数据存储。因此,将覆盖由于选择更改而对链接模型的本地更新。而且,以后实现真正的持久性也不起作用 缩小问题范围 在IndexRoute中,我初始化模型:
model: function(params) {
return {
labels: this.get("store").find("label"),
// TODO: this is probably wrong.
links: Ember.A()
};
}
在一侧,我从数据存储中获取标签数据。另一方面,我用一个空的余烬数组初始化链接数据
我认为这是故障的根源,但我不知道如何正确实施。
我试图将其替换为对存储适配器的虚假引用:
this.get(“store”).find(“label”).filter(“\u”)
这既不对,也不能正常工作。然后继续到无法使用存储适配器更新记录的地步:
// TODO: this is probably wrong.
this.get("links").addObject({
name: linkName,
url: linkUrl,
labels: this.selectedLabels
});
/*store.push("link", {
name: newLink,
url: linkUrl,
labels: this.selectedLabels
});*/
等等
Jsbin:
如何正确存储链接数据,以便更改控制器的本地数据不会中断应用程序
编辑:我想我在你的建议中发现了概念上的错误。这是否意味着我也必须处理本地副本
var link = this.get("model");
link.deleteRecord();
link.save().then(function(link) {
var indexController = this.get('controllers.index');
indexController.get("links").removeObject(link);
});
在您的示例中,您使用承诺将对象添加到控制器。在这个代码示例中,承诺永远不会实现-因此它只在没有承诺的情况下工作
同样在LabelController
中,remove方法也应该删除相关链接。如果我在forEach循环中使用deleteRecord
,它只删除一个标签,然后以某种方式使循环退出。这是故意的还是我犯了错误
我已更新您的JsBin。您定义了您的模型吗
App.Label = DS.Model.extend({
title: DS.attr('string'),
links: DS.hasMany('link')
});
App.Link = DS.Model.extend({
name: DS.attr('string'),
url: DS.attr('string'),
labels: DS.hasMany('label')
});
App.IndexRoute = Ember.Route.extend({
model: function() {
this.store.find('label')
}
});
App.LabelController = Ember.ObjectController.extend({
actions:
<!-- functions here -->
});
<script type='text/handlebars' data-template-name="index">
{{#each label in model itemController='label'}}
{{label.title}}
{{#each link in label.links}}
{{link.title}}
{{/each}}
{{/each}}
</script>
App.Label=DS.Model.extend({
标题:DS.attr('string'),
links:DS.hasMany('link')
});
App.Link=DS.Model.extend({
名称:DS.attr('string'),
url:DS.attr('string'),
标签:DS.hasMany('label'))
});
App.IndexRoute=Ember.Route.extend({
模型:函数(){
this.store.find('label'))
}
});
App.LabelController=Ember.ObjectController.extend({
行动:
});
{{{#模型itemController='label'}中的每个标签
{{label.title}
{{{#label.links中的每个链接}
{{link.title}
{{/每个}}
{{/每个}}
我修改了你的JSbin
如果要保留记录,必须使用createRecord()在存储中创建记录,然后使用save()保存记录。新的newLink函数
newLink: function() {
var store = this.get("store"),
linkName = this.get("linkName"),
linkUrl = this.get("linkUrl"),
links = this.get("links"),
selectedLabels = this.get('selectedLabels');
if(selectedLabels.get('length') > 0) {
if(linkName.length > 0 && linkUrl.length > 0) {
var newLink = store.createRecord('link',
{
name: linkName,
url: linkUrl
});
selectedLabels.forEach(function(label){
newLink.get('labels').addObject(label);
});
newLink.save().then(function(link){
links.addObject(link);
});
this.set("linkName", "");
this.set("linkUrl", "");
}
} else {
alert("You have to select a label!");
}
},
对于删除记录来说,使用forEach存在问题,因为对存储的查找结果是一个活动数组。您可以在GitHub中看到此讨论。
因此,您的remove label函数应该是(注意使用toArray()来创建活动阵列的静态副本)
最后请注意,删除记录后,不要忘记对记录进行保存(),jsBin此处:是。它们在Jsbin中。它们有什么问题吗?我在这里做了一些修改:看起来您需要为链接创建一个组件,并将其传递给当前选择的标签。对于{{{{35;模型中的每个标签}{{{{{35; label.links}}中的每个链接}//,由于您有许多关系{{{link.url}{{{{/each}}{/each}}{/each}},因此这将被侧载,或者,您可以传入链接并使用{{{{{{model.labels}中的每个链接}{{{{/each}}。hasMany属性将另一个模型作为父对象的属性进行侧加载。如果您只想让当前实现正常工作,请为模型中的第二个对象创建链接:this.store.find('link')。不知何故,Jsbin对我不起作用。我试图让我当前的实现正常工作。如果将模型引用更改为this.store.find('link'),则首先必须更改所有用途(以前是addObject,然后是store push),依此类推。然后你得到所有链接,不管你过滤什么。我用问题中提到的假过滤器解决了这个问题。然而,它仍然没有像它应该的那样工作,我也无法开始解释自己为什么。这可能会让我发疯:-)希望其他人在花几个小时来弄明白你不能删除for-each循环中的项目之前找到这个答案。谢谢
remove: function() {
var indexController = this.get('controllers.index'),
label = this.get('model'),
linksPromise = this.get('store').find('link');
linksPromise.then(function(links){
links.toArray().forEach(function(link){
var linkLabels = link.get('labels'),
linkLabelsIds = linkLabels.mapProperty('id');
if(linkLabelsIds.contains(label.get("id"))) {
if(linkLabelsIds.get("length") == 1) {
console.log("delete link: "+link.get("name"));
indexController.get("links").removeObject(link);
link.deleteRecord();
link.save();
}
}
});
label.deleteRecord();
label.save();
});
}