2012-04-03 84 views
8

我有一個DS.Store它使用DS.RESTAdapter並且被定義爲這樣的ChatMessage對象:添加項從餘燼數據濾波結果

App.ChatMessage = DS.Model.extend({ 
    contents: DS.attr('string'), 
    roomId: DS.attr('string') 
}); 

。注意,在一個房間(未示出爲簡單起見)存在聊天消息,所以在我的聊天消息控制器(延伸Ember.ArrayController)我只是想加載消息房間裏的用戶目前在:

loadMessages: function(){ 
    var room_id = App.getPath("current_room.id"); 
    this.set("content", App.store.find(App.ChatMessage, {room_id: room_id}); 
} 

這臺contentDS.AdapterPopulatedModelArray我的看法愉快地在{{#each}}區塊中顯示所有返回的聊天消息。

現在它涉及到增加一個新的消息,我有在同一個控制器以下內容:

postMessage: function(contents) { 
    var room_id = App.getPath("current_room.id"); 
    App.store.createRecord(App.ChatMessage, { 
     contents: contents, 
     room_id: room_id 
    }); 

    App.store.commit(); 
} 

這將啓動一個Ajax請求保存在服務器上的消息,都好,到目前爲止,但它不不更新視圖。這很有意義,因爲它是一個篩選結果,如果我刪除了App.store.find上的room_id篩選器,那麼它會按預期進行更新。

嘗試this.pushObject(message)與從App.store.createRecord返回的消息記錄引發錯誤。

如何手動將項目添加到結果?據我所知,似乎沒有辦法,因爲DS.AdapterPopulatedModelArrayDS.FilteredModelArray都是不可變的。

回答

0

我對源代碼的閱讀(DS.Store.find)顯示,你在這個實例中實際接收的是一個AdapterPopulatedModelArray。 FilteredModelArray會在您創建記錄時自動更新。有這種行爲的通過測試。

+0

你說得對,這是一個AdapterPopulatedModelArray。我更新了這個問題 - 抱歉錯誤! – rlivsey 2012-04-08 17:58:47

8

這樣幾個想法:

(參考:https://github.com/emberjs/data/issues/190

如何在數據存儲

正常Model.find()監聽新記錄/ findQuery()將返回你的AdapterPopulatedModelArray,但該數組會站在自己的...它不會知道任何新的東西已經被加載到數據庫

一個Model.find()與無面值ams(或store.findAll())會將所有記錄返回給FilteredModelArray,並且ember-data將把它「註冊」到列表中,並且加載到數據庫中的所有新記錄都將被添加到此數組中。

調用Model.filter(func)會給你一個FilteredModelArray,它也被註冊到商店中...並且商店中的任何新記錄都會導致ember-data到「updateModelArrays」,這意味着它會調用你的過濾功能與新記錄相關聯,如果您返回,那麼它會將其粘貼到您現有的陣列中。

那麼我做了什麼事情:創建商店後立即調用store.findAll(),它給了我一個類型的所有模型的數組......我將它附加到商店.. 。然後在代碼中的任何其他地方,我可以將ArrayList添加到這些列表中..是這樣的:

App.MyModel = DS.Model.extend() 
App.store = DS.Store.create() 
App.store.allMyModels = App.store.findAll(App.MyModel) 

//some other place in the app... a list controller perhaps 
App.store.allMyModels.addArrayObserver({ 
    arrayWillChange: function(arr, start, removeCount, addCount) {} 
    arrayDidChange: function(arr, start, removeCount, addCount) {} 
}) 

如何把一個模型到那些「不可改變的」陣列中的一個:

首先要注意:所有灰燼的數據模型實例(記錄)具有一個clientId屬性...這是一個唯一的整數,用於標識數據存儲區緩存中的模型,不管它是否具有實際 server-id(例如:在執行Model.createRecord之後)。

所以AdapterPopulatedModelArray本身有一個「內容」屬性......它是這些clientId的數組......並且當你遍歷AdapterPopulatedModelArray時,迭代器循環遍歷這些clientId並把你返回完整的模型實例記錄)映射到每個clientId。

SO我做了什麼 (!這並不意味着它是「正確」)是觀看那些的findAll陣列,並推動新的clientId的進入AdapterPopulatedModelArray的內容屬性...是這樣的:

arrayDidChange:function(arr, start, removeCount, addCount){ 
    if (addCount == 0) {return;} //only care about adds right now... not removes... 
     arr.slice(start, start+addCount).forEach(function(item) { 
      //push clientId of this item into AdapterPopulatedModelArray content list 
      self.getPath('list.content').pushObject(item.get('clientId')); 
     }); 
    } 

我可以說的是:「它爲我工作」:)它會在下一個餘燼數據更新中崩潰嗎?完全可能

2

對於這個還在掙扎,你可以通過使用store.filter方法讓自己的動態DS.FilteredArray而不是靜態DS.AdapterPopulatedRecordArray。它takes 3 parameters:類型,查詢和最後一個過濾器回調。

loadMessages: function() { 
    var self = this, 
     room_id = App.getPath('current_room.id'); 

    this.store.filter(App.ChatMessage, {room_id: room_id}, function (msg) { 
    return msg.get('roomId') === room_id; 
    }) 
    // set content only after promise has resolved 
    .then(function (messages) { 
    self.set('content', messages); 
    });   
} 

你也可以做到這一點在沒有額外的雜波模型掛鉤,因爲該模型鉤子將直接接受一個承諾:

model: function() { 
    var self = this, 
     room_id = App.getPath("current_room.id"); 

    return this.store.filter(App.ChatMessage, {room_id: room_id}, function (msg) { 
    return msg.get('roomId') === room_id; 
    }); 
}