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

あなたの例では、プロミスを使用してオブジェクトをコントローラーに追加しました。このコード サンプルでは、​​約束が果たされることはありません。したがって、約束がない場合にのみ機能します。

またLabelController、remove メソッドでは、関連付けられたリンクも削除する必要があります。deleteRecordforEach ループで使用すると、ラベルが 1 つだけ削除され、何らかの形でループが終了します。これは意図的なものですか、それとも私がミスをしたのでしょうか?

JsBin を更新しました。
http://jsbin.com/ucanam/1987/edit

4

2 に答える 2

3

JSbin http://jsbin.com/ucanam/1975/を変更しました

レコードを永続化したい場合は、ストアで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 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();
        });
    }

最後に、レコードを削除した後、レコードに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 に答える