1

私は ember.js RC1 + ember-data rev 11 を使用しています (ただし、モデルのような構成には単純な ajax も必要です)。単純なオブジェクト リストをループしてレコードを表示したい (注 - ここでは基本的な配列のみを作成します)

バインドしたコンテンツには、次のカスタム検索メソッドが定義されています

App.Foo = DS.Model.extend({
    name: DS.attr('string')
}).reopenClass({
    records: [],
    all: function() {
        return this.records;
    },
    find: function() {                                                              
        var self = this;
        $.getJSON('/api/foo/', function(response) {
            response.forEach(function(data) {
              //say I want to kill everything in the array here for some strange reason...
              self.records = [];
              //the template still shows the record ... not an empty list ?
            }, this);
        });
        return this.records;
    }
});

私の他のモデルはこれを直接使用しています

App.Related = DS.Model.extend({
  listings: function() {
    return App.Foo.find();
  }.property()
});

今私のテンプレートの中に

{{#each foo in related.listings}}
  {{foo.name}}<br />
{{/each}}

リストには、デフォルトで配列に入れたものがすべてロードされます (たとえば、createRecord を使用して単純なオブジェクトを追加するとします)。

add: function(record) {
    this.records.addObject(App.Foo.createRecord(record));
},

テンプレートがレンダリングされると、ここにリストされているものが表示されます...しかし、上記のコメントにあるように、レコードを削除するか、バインドされているリストをnullにすることにした場合、これはまったく反映されないようです。

私が持っているように単純な配列をバインドし、スプライスなどの基本的なものを使用してアイテムを削除することは可能ですか? または思い切った self.records = []; ?

self.records.splice(i, 1);

スプライスまたは空の作業の後にクライアントに手動でクエリを実行しても、0 が返されます

console.log(App.Foo.all().get('length'));

最初はレコードが表示されますが、その後、それらがなくなっていることがわかります (まだ html は変更されません)。

4

2 に答える 2

2

私はあなたの質問をこのように理解しました.次の発言はあなたが苦労している点です:

  response.forEach(function(data) {
          //say I want to kill everything in the array here for some strange reason...
          self.records = [];
          //the template still shows the record ... not an empty list ?
        }, this);

テンプレートに空のリストが表示されないのはなぜですか? テンプレートをいつ更新するかを Ember に伝えていないためです。Ember に次のように伝えることができます。

App.Related = DS.Model.extend({
  listings: function() {
    return App.Foo.find();
  }.property("App.Foo.records.@each")
});

Ember は、配列に何かが追加または削除されるたびに、モデルのリスト プロパティを更新する必要があることを認識しています。したがって、ビューを再レンダリングする必要があることがわかります。

「単純なjavascript配列」に関する元の質問に対する追加の発言。Ember を使用する場合、実際には単純な js 配列をインスタンス化しません。宣言する場合:

var a = []; // is the same as -> var a = Ember.A();

Ember はいくつかの魔法を実行し、配列の強化された ember バージョン (Ember.NativeArray) でラップします。これにより、上記のようなプロパティ依存宣言を使用できます。これにより、Ember はこれらの配列で ArrayObservers を使用できますが、プレーンな JS 配列のように感じるかもしれません。

于 2013-03-04T10:31:36.910 に答える
1

setプロパティを変更するとき、およびプロパティを返すときにこのメソッドを使用する必要がありますget。そうしないと、Emberはその魔法を実行してテンプレートを更新できなくなります。

あなたの場合、追加の問題があります。それは、で、非同期呼び出しがそれを新しい空の配列に置き換える前にfind()、への参照を返すことです。呼び出し元のメソッドは、レコードの新しい配列を見ることはありません。おそらく代わりに使用したいと思うでしょう。recordsgetJSONclear()

モデルは次のようになります。

App.Foo = DS.Model.extend({
    name: DS.attr('string')
}).reopenClass({
    records: [],
    all: function() {
        // can't use 'this.get(...)' within a class method
        return Ember.get(this, 'records');
    },
    findAll: function() {
        var records = Ember.get(this, 'records');
        $.getJSON('/api/foo/', function(response) {
            records.clear();

            // in this case my json has a 'foos' root 
            response.foos.forEach(function(json) {
                this.add(json);
            }, this);
        }, this);

        // this gets updated asynchronously
        return records;
    },
    add: function(json) {
        // in order to access the store within a 
        // class method, I cached it at App.store
        var store = App.get('store');
        store.load(App.Foo, json);

        var records = Ember.get(this, 'records');
        records.addObject(App.Foo.find(json.id));
    }
});

このaddObject()メソッドはオブザーバーを尊重するため、テンプレートは期待どおりに更新されることに注意してください。removeObject()要素を削除するための対応するバインディング対応メソッドです。

これが動作するjsfiddleです。

于 2013-03-04T07:06:26.340 に答える