【问题标题】:ext js multiple instances of same gridext js 同一个网格的多个实例
【发布时间】:2013-03-24 12:23:11
【问题描述】:

我遇到了一个 ext js 网格的多个实例都显示相同数据的问题。我正在使用 Ext js 4.1.1。

我有一个主标签面板。在该面板中,有多个人员选项卡。每个人选项卡内都有一个详细信息选项卡和一个家庭选项卡。

详细信息选项卡是一个简单的表单,包含文本框、组合框等。家庭选项卡具有数据视图和网格。

如果一次只打开一个人选项卡,则一切正常。一旦打开第二个人,家庭选项卡看起来相同(数据视图和网格)。在我看来,这个问题与模型有关。也许他们共享模型的同一个实例,这导致一次刷新就改变了所有数据。数据视图和网格都有同样的问题,但我认为如果我可以解决网格的问题,那么我可以应用相同的逻辑来修复数据视图。除非它变得相关,否则我会将数据视图的代码留在这个问题之外。

PersonTab.js

Ext.require('Client.view.MainTab.PersonDetailsForm');
Ext.require('Client.view.MainTab.PersonFamilyForm');
Ext.require('Client.view.MainTab.EventForm');

Ext.define('Client.view.MainTab.PersonTab',
{
    extend: 'Ext.tab.Panel',
    waitMsgTarget: true,
    alias: 'widget.MainTabPersonTab',
    layout: 'fit',
    activeTab: 0,
    tabPosition: 'bottom',
    items:
        [
            {
                title: 'Details',
                closable: false,
                xtype: 'MainTabPersonDetailsForm'
            },
            {
                title: 'Family',
                closable: false,
                xtype: 'MainTabPersonFamilyForm'
            },
            {
                title: 'page 3',
                closable: false,
                xtype: 'MainTabEventForm'
            }
        ]
});

MainTabPersonFamilyForm.js

Ext.require('Client.view.MainTab.PersonFamilyHeadOfHouseholdDataView');
Ext.require('Client.view.MainTab.PersonFamilyGrid');

Ext.define('Client.view.MainTab.PersonFamilyForm',
{
    extend: 'Ext.form.Panel',
    alias: 'widget.MainTabPersonFamilyForm',
    waitMsgTarget: true,
    padding: '5 0 0 0',
    autoScroll: true,
    items:
        [
            {
                xtype: 'displayfield',
                name: 'HeadOfHouseholdLabel',
                value: 'The head of my household is:'
            },
            {
                xtype: 'MainTabPersonFamilyHeadOfHouseholdDataView'
            },
            {
                xtype: 'checkboxfield',
                boxLabel: "Use my Head of Household's address as my address",
                boxLabelAlign: 'after',
                inputValue: true,
                name: 'UseHeadOfHouseholdAddress',
                allowBlank: true,
                padding: '0 20 5 0'
            },
            {
                xtype: 'MainTabPersonFamilyGrid'
            }
        ],
    config:
        {
            idPerson: ''
        }
});

MainTabPersonFamilyGrid.js

Ext.require('Client.store.PersonFamilyGrid');
Ext.require('Ext.ux.CheckColumn');

Ext.define('Client.view.MainTab.PersonFamilyGrid',
{
    extend: 'Ext.grid.Panel',
    alias: 'widget.MainTabPersonFamilyGrid',
    waitMsgTarget: true,
    padding: '5 0 0 0',
    xtype: 'grid',
    title: 'My Family Members',
    store: Ext.create('Client.store.PersonFamilyGrid'),
    plugins: Ext.create('Ext.grid.plugin.CellEditing'),
    viewConfig:
        {
            plugins:
                {
                    ptype: 'gridviewdragdrop',
                    dragGroup: 'PersonFamilyGridTrash'
                }
        },
    columns:
        [
            { text: 'Name', dataIndex: 'Name'},
            { text: 'Relationship', dataIndex: 'Relationship', editor: { xtype: 'combobox', allowblank: true, displayField: 'display', valueField: 'value', editable: false, store: Ext.create('Client.store.Gender') }},
            { xtype: 'checkcolumn', text: 'Is My Guardian', dataIndex: 'IsMyGuardian', editor: { xtype: 'checkboxfield', allowBlank: true, inputValue: true }},
            { xtype: 'checkcolumn', text: 'I Am Guardian', dataIndex: 'IAmGuardian', editor: { xtype: 'checkboxfield', allowBlank: true, inputValue: true } }
        ],
    height: 200,
    width: 400,
    buttons:
        [
            {
                xtype: 'button',
                cls: 'trash-btn',
                iconCls: 'trash-icon-large',
                width: 64,
                height: 64,
                action: 'trash'
            }
        ]
});

PersonFamilyGrid.js(商店)

Ext.require('Client.model.PersonFamilyGrid');

Ext.define('Client.store.PersonFamilyGrid',
{
    extend: 'Ext.data.Store',
    autoLoad: false,
    model: 'Client.model.PersonFamilyGrid',
    proxy:
        {
            type: 'ajax',
            url: '/Person/GetFamily',
            reader:
                {
                    type: 'json'
                }
        }
});

PersonFamilyGrid.js(模型)

Ext.define('Client.model.PersonFamilyGrid',
{
    extend: 'Ext.data.Model',
    fields:
        [
            'idFamily',
            'idPerson',
            'idFamilyMember',
            'Name',
            'Relationship',
            'IsMyGuardian',
            'IAmGuardian'
        ]
});

来自控制器的相关代码:

....
....
var personTab = thisController.getMainTabPanel().add({
     xtype: 'MainTabPersonTab',
     title: dropData.data['Title'],
     closable: true,
     layout: 'fit',
     tabpanelid: dropData.data['ID'],
     tabpaneltype: dropData.data['Type']
});

personTab.items.items[0].idPerson = dropData.data['ID'];
personTab.items.items[1].idPerson = dropData.data['ID'];

thisController.getMainTabPanel().setActiveTab(personTab);
....
....

【问题讨论】:

    标签: extjs model grid store


    【解决方案1】:

    您将store 设置为网格原型上的属性,并在类定义时创建一次。这意味着从该类实例化的所有网格都将共享完全相同的存储。

    请注意,您还创建了一个 cellediting 插件,该插件也将与该网格的所有实例共享。那肯定行不通。您可能只能在实例化的第一个或最后一个网格中进行编辑。

    一般来说,您不应在类原型上设置storepluginsviewConfigcolumns 之类的属性。相反,您应该覆盖 initComponent 并将它们设置在该方法中,以便您的网格的每个实例都获得这些属性的唯一副本。

    Ext.define('Client.view.MainTab.PersonFamilyGrid', {
        extend: 'Ext.grid.Panel',
        alias: 'widget.MainTabPersonFamilyGrid',
        waitMsgTarget: true,
        padding: '5 0 0 0',
        title: 'My Family Members',
        height: 200,
        width: 400
    
        initComponent: function() {
            Ext.apply(this, {
                // Each grid will create its own store now when it is initialized.
                store: Ext.create('Client.store.PersonFamilyGrid'),
                // you may need to add the plugin in the config for this
                // grid
                plugins: Ext.create('Ext.grid.plugin.CellEditing'),
                viewConfig: {
                    plugins: {
                        ptype: 'gridviewdragdrop',
                        dragGroup: 'PersonFamilyGridTrash'
                    }
                },
                columns: /* ... */
            });
    
            this.callParent(arguments);
        }
    });
    

    【讨论】:

    • 这很好用。 initComponent() 通常会进入视图定义吗?我认为它应该进入控制器。我尝试将它放在控制器中并在渲染事件中加载网格数据,但数据不会显示出来。不过,将 initComponent() 放在视图中是可行的。
    • initComponent 是属于Ext.Component 及其所有子类的方法。 Ext.app.Controller 不是一个组件。 initComponent 在组件初始化时由构造函数调用。您可以在传递给构造函数的配置对象中设置这些属性,而不是在类定义时配置所有内容。大多数时候不需要扩展网格并创建自己的网格,您只需创建一个普通网格并将所需的配置(存储、列、插件等)传递给构造函数。
    【解决方案2】:

    很难准确判断,但从您提交的代码看来,您没有在选项卡和商店​​上设置 id 参数,这会导致 DOM 冲突,因为 id 用于制作组件全球独一无二。这让我在过去对组件(例如选项卡和商店​​)进行子类化并使用这些类的多个实例时感到悲痛。

    尝试给每个人一个唯一的标识符(例如人员 ID),然后使用该 ID 引用他们:

    var personTab = thisController.getMainTabPanel().add({
        id: 'cmp-person-id',
        xtype: 'MainTabPersonTab',
        ...
    
    store: Ext.create('Client.store.PersonFamilyGrid',
    {
        id: 'store-person-id',
        ...
    });
    
    Ext.getCmp('cmp-person-id');
    
    Ext.StoreManager.lookup('store-person-id');
    

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 2012-08-20
      • 1970-01-01
      • 1970-01-01
      • 2014-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-11
      • 1970-01-01
      相关资源
      最近更新 更多