EXTJS4——为什么不&x27;我的关联存储是否加载子数据?

EXTJS4——为什么不&x27;我的关联存储是否加载子数据?,extjs,extjs4,extjs-mvc,Extjs,Extjs4,Extjs Mvc,我有一个父母和孩子的商店,如图所示: 父模型 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: 'st

我有一个父母和孩子的商店,如图所示:

父模型

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'
});
子模型

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调用,我正在加载
客户机
存储,这很好。但是
网站
存储区没有填充,当我在
客户端
存储on.load函数上断点时,要查看填充的内容,
客户端
存储区仅填充客户端数据,但在该存储区的
原始
属性中,我可以看到所有
网站
数据。因此它被正确返回,但我的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'
    }]
});
网站商店

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

你的假设是错误的。您希望网站存储自行加载,但实际情况并非如此。您可以执行以下操作(这未经测试,但我在所有项目中都是这样做的):

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

showWebSites: function (sender, selectedClient) {
    Ext.StoreManager.lookup('APP.store.Websites')
       .loadData(selectedClient.data.WebSites);
}
就是这样。我希望您觉得它有用。

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

确保在同一文件中或应用程序的早期版本中,您需要相关型号

如果您想随意加载相关数据(即,在以后的网络请求中),请使用
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'
    }
    }
});
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'
    }
    }
});
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);
            }
        });
        }
    });

    }
});
model/PhoneNumber.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'
    }
    }
});
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'
    }
    }
});
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);
            }
        });
        }
    });

    }
});
data/contacts.json:

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

}
data/phone-numbers.json

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

}
app.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'
    }
    }
});
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'
    }
    }
});
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()。

当您使用关联时,extjs不使用您的网站存储。相反,它创建了自己的普通存储。有关更多信息,请查看我的答案。以您的示例为例,似乎我需要执行
selectedClient.websites().load()
,但我面临同样的问题。相关数据没有正确加载到存储/模型中(请注意我对下面答案的评论),因此我得到错误
对象没有方法“网站”
。当数据从服务器返回时,它没有正确加载到模型/存储中,因此其中一个存在配置问题。然后当我将
hasMany:{model:'Website',name:'websites'}
更改为
hasMany:{model:'APP.model.Website',name:'websites'}
我收到一个新错误
无法调用未定义的方法“indexOf”
。看起来它正在识别websites()方法,但我现在有一个新错误。我将逐步查看调试文件以尝试查看发生了什么。运行此
selectedClient.websites().load()
时,它似乎找到了带有
websites()
的正确存储,但代理中没有配置URL。正如您在上面的定义中所看到的,实际上我在代理服务器上配置了一个URL…这是有意义的,但是
selectedClient.data.websites
中没有包含任何内容。但是,数据在
selectedClient.raw.websites
中,它告诉我数据正在从服务器返回,但没有正确加载。因此,我的模型/商店中的某些内容不正确。我要补充的是,使用
selectedClient.raw.websites
加载它是可行的,但似乎不是正确的解决方案感谢notes&code示例。这真的很有帮助!我注意到你的电话号码模型中没有使用
belongsTo
。如果父模型是按您现有的方式配置的,则无需使用belongsTo。如果您试图从子模型引用父模型,则只需使用belongsTo。你不需要它从父母那里引用孩子。谢谢你的解决方案帮助我找到了我的问题。注意从ArrayStore派生存储类,即扩展:“Ext.data.ArrayStore”。您将得到一个
Ext.data.reader.Array
,它将悄悄地覆盖您配置的Json读取器,并在加载嵌套数据时让您挠头数小时,但您的父数据尚未初始化。