7

アプリケーションのルーターを介してEmberDataREST呼び出しから供給されるArrayControllerをアプリケーションで使用しています。

postsController.connectOutlet('comment', App.Comment.find({post_id: post_id}));

投稿UIの場合、コメントを追加/削除することができます。これを行うとき、同じ要素を削除または追加してユーザーに視覚的なフィードバックを提供することで、postsControllerのcontentArrayを更新できるようにしたいのですが、EmberDataは面白くありません。

Uncaught Error: The result of a server query (on App.Comment) is immutable.

以下のsly7_7のコメントによると、クエリがない場合(App.Comment.find())、クエリがある場合(App.Comment.find({post_id: post_id})、DS.AdapterPopulatedRecordArrayが返されます。

.observes('contentArray')して、可変コピーを作成する必要がありますか?それとも、これを行うためのより良い方法はありますか?

4

4 に答える 4

7

これを解決するために私が最終的に実装したものは次のとおりです。質問で提案されているように、私が知っている唯一の解決策は、追加と削除を通じて維持するコンテンツの変更可能なコピーを作成することです。

contentChanged: function() {
    var mutableComments = [];

    this.get('content').forEach(function(comment) {
        mutableComments.pushObject(comment);
    });

    this.set('currentComments', mutableComments);
}.observes('content', 'content.isLoaded'),

addComment: function(comment) {
    var i;
    var currentComments = this.get('currentComments');
    for (i = 0; i < this.get('currentComments.length'); i++) {
        if (currentComments[i].get('date') < comment.get('date')) {
            this.get('currentComments').insertAt(i, comment);
            return;
        }
    }

    // fell through --> add it to the end.
    this.get('currentComments').pushObject(comment);
},

removeComment: function(comment) {
    this.get('currentComments').forEach(function(item, i, currentComments) {
        if (item.get('id') == comment.get('id')) {
            currentComments.removeAt(i, 1);
        }
    });
}

次に、テンプレートで、この計算されたプロパティにバインドします。

{{#each comment in currentComments}}
    ...
{{/each}}

私はこの解決策に満足していません。もっと良い方法があれば、ぜひ教えてください。

于 2012-08-13T16:35:23.513 に答える
2

コメントが長くなりそう…

どのようにレコードを追加しようとしているのかわかりませんが、これを試すことができます: App.Comment.createRecord({}). すべてがうまくいけば、コントローラーのコンテンツが自動的に更新されます。( App.Comment.find() の結果は「ライブ」配列として機能し、レコードを作成すると自動的に更新されると思います)アプリでこれを行う方法は次のとおりです。

App.ProjectsRoute = Ember.Route.extend({
  route: 'projects',

  collection: Ember.Route.extend({
    route: '/',

    connectOutlets: function (router) {
      router.get('applicationController').connectOutlet({
        name: 'projects',
        context: App.Project.find()
      });
    }
 })

次に、プロジェクトを作成するハンドラー (ルーター内):

createProject: function (router) {
  App.Project.createRecord({
    name: 'new project name'.loc()
  });
  router.get('store').commit();
},
于 2012-08-10T19:16:43.103 に答える
0

序文

私は同様の問題を抱えていて、少しトリッキーな解決策を見つけました。Ember-Data ソース コードと API ドキュメントを実行すると、照会された検索要求から AdapterPopulatedRecordArray が返されるという事実が明らかになりました。それはマニュアルが言うことです:

AdapterPopulatedRecordArray は、順序とメンバーシップがアダプターによって決定されるレコードの順序付きリストを表します。たとえば、アダプタに送信されたクエリは、サーバー上で検索をトリガーする場合があり、その結果は AdapterPopulatedRecordArray のインスタンスにロードされます。

したがって、不変性の正当な理由は、このデータがサーバーによって制御されることです。しかし、それが必要ない場合はどうなりますか?たとえば、多数のタスクを持つ Tasklist モデルがあり、次のような方法で TasklistController でそれらを見つけます

this.get('store').find('task',{tasklist_id: this.get('model').get('id')})

また、新しいレコードを作成して保存する必要がある大きな赤いボタン「タスクの追加」がありますが、テンプレートを再描画して新しいタスクを表示するためにサーバーに新しい検索リクエストを作成したくありません。私にとって良い習慣は次のようなものになります

var task = this.store.createRecord('task', {
    id: Utils.generateGUID(),
    name: 'Lorem ipsum'
});
this.get('tasks').pushObject(task);

その場合、エラーが発表されました。でもね、飲酒運転したい!

解決

DS.AdapterPopulatedRecordArray.reopen({
    replace: DS.RecordArray.replace
})

それだけです。少し「自分で」の残り火の柔軟性のハック。

于 2015-03-14T18:01:35.567 に答える