将项添加到来自ember-data的过滤结果中

rli*_*sey 8 ember.js ember-data

我有一个DS.Store使用DS.RESTAdapterChatMessage定义的对象:

App.ChatMessage = DS.Model.extend({
    contents: DS.attr('string'),
    roomId:   DS.attr('string')
});
Run Code Online (Sandbox Code Playgroud)

请注意,房间中存在聊天消息(为简单起见未显示),因此在我的聊天消息控制器(扩展Ember.ArrayController)中,我只想为用户当前所在的房间加载消息:

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

这将设置content为a DS.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();
}
Run Code Online (Sandbox Code Playgroud)

这会启动ajax请求以在服务器上保存消息,到目前为止一切都很好,但它不会更新视图.这非常有意义,因为它是一个过滤结果,如果我删除了room_id过滤器,App.store.find那么它会按预期更新.

尝试this.pushObject(message)使用返回的消息记录App.store.createRecord会引发错误.

如何手动将项目添加到结果中?似乎没有成为一个办法,据我可以告诉既DS.AdapterPopulatedModelArrayDS.FilteredModelArray是不可变的.

Nic*_*ina 8

所以几个想法:

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

如何监听数据存储区中的新记录

一个正常的Model.find()/ findQuery()将返回一个AdapterPopulatedModelArray,但该数组将独立...它不会知道任何新的已加载到数据库

没有params(或store.findAll())的Model.find()将返回所有记录FilteredModelArray,并且ember-data将"注册"到列表中,并且任何加载到数据库中的新记录都将添加到这个数组.

调用Model.filter(func)将返回一个FilteredModelArray,它也在商店中注册...并且商店中的任何新记录都会导致ember-data为"updateModelArrays",这意味着它将调用你的过滤器函数新记录,如果你返回true,那么它会将它粘贴到你现有的数组中.

那么我结束了什么:在创建商店之后,我立即调用了store.findAll(),它给了我一个类型的所有模型数组......然后我将它附加到商店......然后在其他任何地方在代码中,我可以addArrayObservers到这些列表..类似于:

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) {}
})
Run Code Online (Sandbox Code Playgroud)

如何将模型推入其中一个"不可变"数组:

首先要注意:所有Ember-Data Model实例(记录)都有一个clientId属性...这是一个唯一的整数,用于标识数据存储区缓存中的模型,无论它是否具有真正的服务器ID(例如:一个Model.createRecord).

所以AdapterPopulatedModelArray本身有一个"内容"属性...这是这些clientId的数组......当你遍历AdapterPopulatedModelArray时,迭代器遍历这些clientId并递回你映射的完整模型实例(记录)到每个clientId.

那么我 做了什么(这并不意味着它是"正确的"!)是观察那些findAll数组,并将新的clientId推送到AdapterPopulatedModelArray的content属性... SOMETHING LIKE:

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'));
        });
    }
Run Code Online (Sandbox Code Playgroud)

我能说的是:"它为我工作":)它会破坏下一个余烬数据更新吗?完全有可能


Chr*_*sey 0

我对源代码(DS.Store.find)的阅读表明,在此实例中您实际收到的是 AdapterPopulatedModelArray。FilteredModelArray 将在您创建记录时自动更新。这种行为已经通过了测试。