【问题标题】:EXTJS4--Why don't my associated stores load child data?EXTJS4--为什么我的关联商店不加载子数据?
【发布时间】:2012-05-31 15:19:05
【问题描述】:

所以我有一个父子商店,如下所示:

父模型

Ext.define('APP.model.Client', {
    extend: 'Ext.data.Model',
    requires: [
        'APP.model.Website', 'Ext.data.association.HasMany', 'Ext.data.association.BelongsTo'],
    fields: [{
        name: 'id',
        type: 'string'
    }, {
        name: 'name',
        type: 'string'
    }, {
        name: 'slug',
        type: 'string'
    }, {
        name: 'active',
        type: 'boolean'
    }, {
        name: 'current',
        type: 'boolean'
    }],
    hasMany: {
        model: 'APP.model.Website',
        name: 'websites'
    }
});

儿童模型

Ext.define('APP.model.Website', {
    extend: 'Ext.data.Model',
    fields: [{
        name: 'id',
        type: 'string'
    }, {
        name: 'client_id',
        type: 'string'
    }, {
        name: 'sub_domain',
        type: 'string'
    }, {
        name: 'active',
        type: 'boolean'
    }],
    belongsTo: 'APP.model.Client'
});

通过服务器使用 AJAX 调用,我正在加载 Clients 存储,并且加载正常。但是 Websites 存储没有填充,当我在 Clients 存储 on.load 函数上断点时,查看它填充了什么,Client 存储仅填充了客户端数据,但在 @该商店的 987654328@ 属性,我可以看到所有 websites 数据。所以它被正确返回,但我的 extjs 不正确。这里是商店:

客户端商店

Ext.define('APP.store.Clients', {
    extend: 'Ext.data.Store',
    autoLoad: false,
    model: 'APP.model.Client',
    proxy: {
        type: 'ajax',
        url: '/client/list',
        reader: {
            type: 'json',
            root: 'items'
        }
    },
    sorters: [{
        property: 'name',
        direction: 'ASC'
    }]
});

网站商店

Ext.define('APP.store.Websites', {
    extend: 'Ext.data.Store',
    requires: ['Ext.ux.Msg'],
    autoLoad: false,
    model: 'APP.model.Website',
    proxy: {
        type: 'ajax',
        url: '/client/list',
        reader: {
            type: 'json',
            root: 'items'
        },
        writer: {
            type: 'json'
        }
    },
    sorters: [{
        property: 'sub_domain',
        direction: 'ASC'
    }]
});

我的最终结果是...我想填充两个商店,以便我可以单击一个元素,当它从父商店加载某些内容时,我可以访问子商店(当我发现了这个问题)在选项卡中填充几个网格。

就我的设置而言,我缺少什么?几天前我刚刚下载了extjs4,所以我在4.1上。

【问题讨论】:

  • 当您使用关联时,extjs 并未使用您的网站商店。相反,它创建了自己的普通商店。有关更多信息,请查看我的回答 here
  • 以你的例子,看来我需要做selectedClient.websites().load(),但我面临同样的问题。相关数据未正确加载到存储/模型中(请注意我对下面答案的评论),因此我收到错误 Object has no method 'websites'。从服务器返回数据时,它没有正确加载到模型/存储中,因此其中一个存在配置问题。
  • 然后当我将hasMany: {model: 'Website', name: 'websites'} 更改为hasMany: {model: 'APP.model.Website', name: 'websites'} 时,我收到一个新错误Cannot call method 'indexOf' of undefined。所以看起来它正在识别 website() 方法,但我现在有一个新错误。我将通过调试文件来尝试看看发生了什么。
  • 当我运行这个selectedClient.websites().load() 时,它看起来好像找到了带有websites() 的正确存储,但是代理中没有配置 URL。正如您在我上面的定义中看到的那样,我确实在代理上配置了一个 URL...

标签: extjs extjs4 extjs-mvc


【解决方案1】:

你的假设是错误的。您希望网站商店自行加载,但这不是它的工作方式。您可以执行以下操作(未经测试,但我在所有项目中都是这样做的):

在您的客户端网格中,为 itemclick 事件添加一个侦听器以调用以下方法 (showWebSites)。它将接收包含所选 APP.model.Client 实例的所选客户端记录。然后,假设每个客户端都有一组网站,该方法将加载 APP.store.Websites 商店,并且客户端的网站将显示在您的视图中。

showWebSites: function (sender, selectedClient) {
    Ext.StoreManager.lookup('APP.store.Websites')
       .loadData(selectedClient.data.WebSites);
}

就是这样。我希望你觉得它有用。

【讨论】:

  • 这是有道理的,但selectedClient.data.websites 中不包含任何内容。但是,数据在selectedClient.raw.websites 中,这告诉我数据正在从服务器返回,但未正确加载。所以我的模型/商店里有些东西是不正确的。
  • 我会补充一点,使用selectedClient.raw.websites 加载它是可行的,但似乎不是正确的解决方案
【解决方案2】:

将您的代理放入您的模型,除非您有充分的理由不 [1]

确保您require 相关模型,无论是在同一个文件中,还是在应用程序的早期

如果您想随意加载相关数据(即通过稍后的网络请求),请使用foreignKey

如果相关数据加载到同一个(嵌套)响应中,则使用associationKey

或者两个都用

始终name您的关系(否则如果使用命名空间,名称会很奇怪)。

始终为您的关系中的model 属性使用完全限定的模型名称

工作代码:

model/Contact.js:

Ext.define('Assoc.model.Contact', {
    extend:'Ext.data.Model',

    requires:[
    'Assoc.model.PhoneNumber' 
    ],

    fields:[
    'name' /* automatically has an 'id' field */
    ],

    hasMany:[
    {
        model:'Assoc.model.PhoneNumber', /*use the fully-qualified name here*/
        name:'phoneNumbers', 
        foreignKey:'contact_id',
        associationKey:'phoneNumbers'
    }
    ],

    proxy:{
    type:'ajax',
    url:'assoc/data/contacts.json',
    reader:{
        type:'json',
        root:'data'
    }
    }
});

model/PhoneNumber.js:

Ext.define('Assoc.model.PhoneNumber', {
    extend:'Ext.data.Model',

    fields:[
    'number',
    'contact_id'
    ],

    proxy:{
    type:'ajax',
    url:'assoc/data/phone-numbers.json',
    reader:{
        type:'json',
        root:'data'
    }
    }
});

数据/contacts.json:

{
    "data":[
    {
    "id":1,
    "name":"neil",
    "phoneNumbers":[
    {
        "id":999,
        "contact_id":1,
        "number":"9005551234"
    }
    ]
    }
    ]

}

数据/电话号码.json

{
    "data":[
    {
    "id":7,
    "contact_id":1,
    "number":"6045551212"
    },
    {
    "id":88,
    "contact_id":1,
    "number":"8009996541"
    },
    ]

}

app.js:

Ext.Loader.setConfig({
    enabled:true
});

Ext.application({

    requires:[
    'Assoc.model.Contact'
    ],

    name:'Assoc',
    appFolder:'Assoc',

    launch:function(){

    /* load child models that are in the response (uses associationKey): */
    Assoc.model.Contact.load(1, {
        success: function(record){
        console.log(record.phoneNumbers());
        }
    });

    /* load child models at will (uses foreignKey). this overwrites child model that are in the first load response */
    Assoc.model.Contact.load(1, {
        success: function(record){
        record.phoneNumbers().load({
            callback:function(){
            console.log(arguments);
            }
        });
        }
    });

    }
});

[1] 商店将使用其模型的代理。如果需要,您可以随时覆盖商店的代理。如果模型没有代理,您将无法使用 Model.load()。

【讨论】:

  • 感谢您的注释和代码示例。这真的很有帮助!我注意到您没有在 PhoneNumber 模型中使用 belongsTo。如果父模型按照您的方式配置,则不需要?
  • 只有在尝试从子节点引用父节点时才需要使用 belongsTo。您不需要它来从父级引用子级。
  • 感谢您的解决方案帮助我找到了我的问题。请注意从 ArrayStore 派生您的商店类,即extend: 'Ext.data.ArrayStore'。最后你会得到一个Ext.data.reader.Array,它会默默地覆盖你配置的 Json 阅读器,让你在加载嵌套数据时摸不着头脑,但你的父数据未初始化。
猜你喜欢
  • 1970-01-01
  • 2011-10-14
  • 1970-01-01
  • 1970-01-01
  • 2011-09-01
  • 2017-05-07
  • 1970-01-01
  • 1970-01-01
  • 2016-02-28
相关资源
最近更新 更多