3

为了学习 Ember.js,我开始编写一个小型书签应用程序。我现在正在努力解决与错误数据处理相关的问题。

解释应用程序

  • 用户可以添加标签
  • 用户可以添加链接到选定的标签
  • 一个标签可以有 n 个链接
  • 一个链接可以有 n 个标签
  • 通过选择相关标签显示链接

问题
链接数据不会写入数据存储。因此,由于选择更改而对链接模型进行的本地更新将被覆盖。此外,以后实现真正的持久性也行不通。

缩小问题范围

在 IndexRoute 我初始化模型:

model: function(params) {
    return {
        labels: this.get("store").find("label"),
        // TODO: this is probably wrong.
        links: Ember.A()
    };
}

一方面,我从数据存储中获取标签数据。另一方面,我用一个空的 ember 数组初始化链接数据。

我认为这是故障的根源,但我不知道如何正确实施。我试图用对存储适配器的虚假引用来替换它:

this.get("store").find("label").filter("_")

这既不正确,也不能正常工作。然后它继续到我无法使用存储适配器更新记录的地步:

// 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:http: //jsbin.com/ucanam/1751/edit

如何正确存储链接数据,以便更改控制器的本地数据不会破坏应用程序?

编辑:
我想我在你的建议中发现了我的概念错误。这是否意味着我总是必须处理本地副本?

var link = this.get("model");
link.deleteRecord();
link.save().then(function(link) {
    var indexController = this.get('controllers.index');
    indexController.get("links").removeObject(link);
});

在您的示例中,您使用了一个承诺将对象添加到控制器。在这个代码示例中,promise 永远不会实现——因此它只能在没有的情况下工作。

另外在LabelControllerremove方法中也应该删除关联的链接。如果我deleteRecord在 forEach 循环中使用它只会删除一个标签,然后它会以某种方式使循环退出。这是故意的还是我犯了错误?

我已经更新了你的 JsBin。
http://jsbin.com/ucanam/1987/edit

4

2 回答 2

3

我修改了你的 JSbin http://jsbin.com/ucanam/1975/

如果要保留记录,则必须使用createRecord()在 store 中创建它们,然后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 https://github.com/emberjs/data/issues/772中查看此讨论。所以你的删除标签函数应该是(注意使用toArray()来制作实时数组的静态副本)

    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();
        });
    }

最后注意,删除记录后不要忘记在记录上进行保存() ,jsBin在这里:http: //jsbin.com/ucanam/1989/

于 2013-11-05T10:59:49.523 回答
1

你定义了你的模型吗?

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>
于 2013-10-29T17:44:24.483 回答