【问题标题】:ExtJS Automatically populating a model property via an associationExtJS 通过关联自动填充模型属性
【发布时间】:2012-12-15 17:57:36
【问题描述】:

我正在使用 ExtJS 4.1.0

假设我通过hasMany 关联连接了几个简单模型。模型代表一个订单和订单内容...

Ext.define('App.model.Order', 
{
    extend: 'Ext.data.Model',
    fields: ['id', 'order_date', 'order_total', 'contents' ],
    associations: [{
            type           : 'hasMany',
            model          : 'App.model.OrderContents',
            name           : 'getContents', /** magic method */
            primaryKey     : 'id',
            foreignKey     : 'order_id',
            autoLoad       : false
    }],

    /** Proxy Definition here.. */

});

Ext.define('App.model.OrderContents', 
{
    extend: 'Ext.data.Model',
    fields: ['id', 'order_id', 'item_id' ],

    /** Proxy Definition here.. */

});

现在,如果我希望在实例化 Order 模型时自动设置 App.model.Order 的 contents 属性怎么办?作为临时解决方案,我在Order 模型中添加了以下方法:

Ext.define('App.model.Order', 
{

/** Model definition ... */

    loadContents: function()
    {
       this.getContents().load({
            callback: function()
            {
                this.set('contents', arguments[0]);
            },
            scope: this
        });

    }
});

为了使Order 对象的内容随时可用,我必须执行以下操作:

var myOrder = new App.model.Order({id:1, order_date:'12-15-2012', order_total:100});
myOrder.getData(true); // contents will be null
myOrder.loadContents();
myOrder.getData(); // contents will be an array of OrderContents

我尝试重载App.model.Order 的构造函数,但无论如何,即使我对关联数据的异步请求执行回调,我也无法访问关联加载的数据。

最终我希望能够从我的App.store.Orders 中检索一个订单,并让检索到的记录已经设置了它的contents 属性,但我就是想不通!如果我从商店中检索记录如下:

myStore = Ext.getStore('OrderStore');
myOrder = myStore.findRecord('id',1);
myOrder.getData(); // contents will be null
myOrder.loadContents();
myOrder.getData(); // contents will be an array of OrderContents

我真的只是想减少在整个应用程序中为App.model.Order 的每个实例使用.loadContents();这似乎应该很容易完成。我错过了什么?!

感谢您的宝贵时间!

【问题讨论】:

    标签: javascript extjs extjs4 model-associations


    【解决方案1】:

    您提到您使用 constructor 进行了尝试,但我认为您做错了什么。如果您的构造函数如下所示:

    constructor: function(){
        var me = this;
        me.callParent([arguments]);
        me.loadContents();
    }
    

    我想你会得到想要的结果...

    【讨论】:

    • 我或多或少地尝试过这种方法。尝试调用loadContents 时,我收到错误“无法调用未定义的方法'调用'”。我已经设法解决了,请参阅我的以下评论。我重载了 store 构造函数。
    【解决方案2】:

    这没有经过测试,但它应该可以工作。

    Ext.define('App.model.Order', 
    {
        extend: 'Ext.data.Model',
        fields: ['id', 'order_date', 'order_total', 'contents' ],
        associations: [{
                type           : 'hasMany',
                model          : 'App.model.OrderContents',
                name           : 'getContents', /** magic method */
                primaryKey     : 'id',
                foreignKey     : 'order_id',
                autoLoad       : false
        }],
        load: function(id, config) {
                config = Ext.apply({
                      success: function(record, operation) {
                            store.getContents().load();
                      },
                }, config);
                this.callParent([id, config]);
        },
        /** Proxy Definition here.. */
    
    });
    

    更新: 您可以编写自己的加载方法(在示例中称为 loadAll),如下所示:

        Ext.define('App.model.OrderContents', 
        {
             extend: 'Ext.data.Model',
             fields: ['id', 'order_id', 'item_id' ],
    
             proxy: {
                    type: 'memory',
                    data: [
                        {id: 1, order_id: 1, item_id: 2}, 
                        {id: 2, order_id: 1, item_id: 3},
                        {id: 3, order_id: 21, item_id: 3}
                    ],
                  reader: 'json'            
             }
    
        });
    
    
        Ext.define('App.model.Order', 
             {
                  extend: 'Ext.data.Model',
                  fields: ['id', 'order_date', 'order_total', 'contents' ],
                  associations: [{
                             type           : 'hasMany',
                             model          : 'App.model.OrderContents',
                             name           : 'getContents', /** magic method */
                             primaryKey     : 'id',
                             foreignKey     : 'order_id',
                             autoLoad       : false
                  }],
                  statics: {
                          loadAll: function(id, config) {
                             config = Ext.apply({
                                     callback: function(record, operation) {
                                         if(operation.wasSuccessful()){
                                            record.getContents().load();
                                            record.set('contents', record.getContents().getRange());
                                             }
                                   },
                                    scope: this
                             }, config);
                             App.model.Order.load(id, config);
                        }
                  },
                  proxy: {
                        type: 'memory',
                        data: {'id':1, 'order_date':null, 'order_total': 100, 'contents':[]},
                        reader: {
                            type: 'json'
                        }
    
                  }
             });
    
    
    var order;
    App.model.Order.loadAll(1,{
        success: function(record){
            order = record;
        }
        });
    
    console.log(order);
    

    ​你可以看到它在 jsfiddle 上运行:

    http://jsfiddle.net/lontivero/X4gfR/

    【讨论】:

    • 我不相信该模型会引发load 事件? docs.sencha.com/ext-js/4-1/#!/api/Ext.data.Model
    • 对于@lontivero 的缓慢响应感到抱歉,这看起来确实是一个优雅的解决方案。为了我的需要,我重载了包含我的订单的商店的构造函数。该方法遍历每个加载的记录并调用我的loadContents 方法,该方法又按预期填充对象的contents 属性。反过来,每当我从订单的商店中检索订单时,它都已经加载了它的内容。再次感谢您富有洞察力的评论和解决方案!
    【解决方案3】:

    我通过重载 store 的构造函数来解决问题:

    Ext.define('App.store.Orders', {
        extend: 'Ext.data.Store',
        storeId: 'OrdersStore',
        model: 'App.model.Order',
    
        constructor: function()
        {
            this.superclass.constructor.call(this);
            this.on('load', function(store, records, success, eOpts){
                Ext.each(records, function(order){
                   order.loadContents();
                });
            }, this);
        }
    });
    

    希望这会对某人有所帮助:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多