Ember.js ArrayProxy模型数组

时间:2012-05-24 18:31:24

标签: model ember.js

目标

创建一个由ArrayController(ArrayProxy)管理的Model数组。 要求

使用ArrayController(ArrayProxy)抽象来封装Model的数组 插入到ArrayProxy后,将对象输入自动转换为ArrayProxy 不要在访问时间进行延迟转换

示例数据结构

App.AddressModel = Ember.Object.extend({
    address_name: null,
    address: null,
    printme: function() {
        console.log("Just making sure the array turned into an AddressModel");
    },
});

App.addressArray = Ember.ArrayProxy.create({
    transformFrom: function(item) {
    },
    transformTo: function(item) {
    },
    arrayContentWillChange: function(startIdx, removeAmt, addAmt) {
    },
});

审判失败

动态属性

IRC频道中有人提到尝试动态属性。这导致了一个似乎是逻辑和经验证据的递归结果。毫无疑问,将内容设置为动态生成的变量和“触发/导出”变量。

arrayContentWillChange

再一次,看似递归的结果。收到arrayContentWillChange通知后,我从给定的数组索引项生成一个AddressModel。然后我将旧的索引项设置为创建的Model,再次触发arrayContentWillChange事件,重复... recurse。

transformFrom / transformTo

https://github.com/emberjs/ember.js/pull/554#issuecomment-5401112 tomdale在上面的帖子中提到尝试使用transformFrom和transformTo来转换传入和/或传出的数据。这些功能似乎不存在[http://cloud.github.com/downloads/emberjs/ember.js/ember-0.9.8.js]。

ArrayProxy模型补丁

https://github.com/emberjs/ember.js/pull/554 tomdale对这个问题的原始解决方案/帖子的建议似乎比jedwood引入的模型实现更好,但是,Backbone.js通过使用特殊的模型变量处理这个问题,我发现它运行良好。

问题

如何扩展ArrayProxy以将要管理的所有传入对象转换为AddressModel?

1 个答案:

答案 0 :(得分:5)

我采用了Tom Dale提到的覆盖replace方法的方法。它还注册了content属性的观察者,以确保内容是数组的类型版本,请参阅http://jsfiddle.net/pangratz666/XCLmE/

App.ModelArrayProxy = Ember.ArrayProxy.extend({
    modelType: Ember.required,

    _typedArray: function(objects) {
        var modelType = this.get('modelType');
        var array = objects.map(function(item) {
            // check if item is an instance of type
            if (!(item instanceof modelType)) {
                // create a new instance of type and pass the hash
                return modelType.create(item);
            }

            // just return the item, since it's already of type modelType             
            return item;
        });
        return array;
    },

    contentChanged: function() {
        if (!this.get('setTypedContent')) {
            var content = this.get('content');

            this.set('setTypedContent', true);
            this.set('content', this._typedArray(content));
            this.set('setTypedContent', false);
        }
    }.observes('content'),

    replace: function(idx, amt, objects) {
        this._super(idx, amt, this._typedArray(objects));
    }
});

然后,可以将此ModelArrayProxy用作“普通”ArrayProxy

// model declaration
App.AddressModel = Ember.Object.extend({
    ...
});

// create a proxy for given modelType
App.proxy = App.ModelArrayProxy.create({
    content: [],
    modelType: App.AddressModel
});

var myArray = [{
    address_name: 'address_name 1',
    address: 'address 1'},
{
    address_name: 'address_name 2',
    address: 'address 2'}];

// set content with "normal" objects
App.proxy.set('content', myArray);

// invoke 'log' on all items in array
App.proxy.forEach(function(item) {
    item.log();
});

// push a normal object
App.proxy.pushObject({
    address_name: 'address_name 3',
    address: 'address 3'
});

// push an instance of App.AddressModel
App.proxy.pushObject(App.AddressModel.create({
    address_name: 'address_name 4',
    address: 'address 4'

}));

// invoke 'log' on all items in array
App.proxy.forEach(function(item) {
    item.log();
});​