0

我确定我在这里缺少一些东西,我只是看不到它是什么。

我有我在 extjs 6 中构建的演示项目。其中我有一个库存项目网格。

Ext.define("InventoryDemo.view.inventory.list.Inventory",{
    extend: "Ext.container.Container",
    xtype: 'inventory',

    requires: [
        "InventoryDemo.view.inventory.list.InventoryController",
        "InventoryDemo.view.inventory.list.InventoryModel"
    ],

    controller: "inventory-inventory",
    viewModel: {
        type: "inventory-inventory"
    },
    closable: true,

    listeners:{
        refreshList: 'onRefreshList'
    },


    layout:{
        type: 'hbox',
        align: 'stretch'
    },
    items:[
        {
            xtype: 'grid',
            flex: 1,

            tbar:[
                {xtype: 'button', text: 'New Item', handler: 'newInventoryItem'}
            ],

            bind:{
                store: '{inventory}'
            },

            listeners:{
                itemclick: 'showDetails'
            },

            columns:[
                { text: 'Name', dataIndex: 'name', flex: 1 },
                { text: 'Price', dataIndex: 'price' },
                { text: 'Active', dataIndex: 'active' },
            ]
        }
    ]
});

当您单击一行时,将创建一个新的详细信息面板,并将所选记录链接到其视图模型,并将其添加到包含网格的容器视图中。我还想在创建新库存记录时使用相同的详细信息面板,因此我提取了用于创建和编辑的共享逻辑,以便可以在控制器中重用它。

这是列表的控制器:

Ext.define('InventoryDemo.view.inventory.list.InventoryController', {
    extend: 'Ext.app.ViewController',
    alias: 'controller.inventory-inventory',

    config:{
        // holds the newly created detail panel
        detailsPanel: null
    },

    showDetails: function (grid, record, item, index, e, eOpts){
        this.createDetailsPanel();
        this.addTitleToDetailsPanel(record.get('name'));

        // This creates the link in the new detail panel's viewmodel for the
        // selected record. We specifically do NOT do this in the
        // `newInventoryItem`.
        details.getViewModel().linkTo('inventoryitem', record);

        this.addDetailsPanelToView();
    },

    newInventoryItem: function (button, e){
        this.createDetailsPanel();
        this.addTitleToDetailsPanel('New Item');

        // I thought that because the previous panel was destroyed during the
        // `createDetailsPanel` method any previously linked record would not
        // be linked to the new detail panel created and that not linking here
        // would give me an empty detail panel.
        this.addDetailsPanelToView();
    },


    createDetailsPanel: function (){
        if(this.getDetailsPanel() !== null){
            // I'm destroying any previous view here which, as I understand, 
            // would also destroy the the associated ViewController and ViewModel
            // which would also kill any links to the viewmodel
            this.getDetailsPanel().destroy();
        }

        details = Ext.create('InventoryDemo.view.inventory.details.Inventory',{
            session: true,
            listeners:{
                refreshList: 'onRefreshList'
            }
        });
        this.setDetailsPanel(details);
    },

    addDetailsPanelToView: function (){
        this.getView().add(this.getDetailsPanel());
    },

    addTitleToDetailsPanel: function (title){
        this.getDetailsPanel().setTitle("<h3>" + title + "</h3>");
    },

    onRefreshList: function (){
        this.getViewModel().get('inventory').load();
    }
});

正在创建的详细信息面板如下所示:

Ext.define("InventoryDemo.view.inventory.details.Inventory",{
    extend: "Ext.form.Panel",

    requires: [
        "InventoryDemo.view.inventory.details.InventoryController",
        "InventoryDemo.view.inventory.details.InventoryModel"
    ],

    controller: "inventory-details-inventory",
    viewModel: {
        type: "inventory-details-inventory"
    },

    flex: 1,
    closable: true,
    bodyPadding: 10,
    reference: 'inventorydetails',
    defaults:{
        layout: 'anchor',
        anchor: '50%'
    },
    dockedItems:[
        {
            xtype: 'toolbar',
            dock: 'bottom',
            ui: 'footer',
            items:[
                {xtype: 'button', text: 'Update', handler: 'updateRecord'},
                {xtype: 'button', text: 'Delete', handler: 'deleteRecord'}
            ]
        }
    ],

    items:[
        {
            xtype: 'hiddenfield',
            name: '_method',
            value: 'PUT'
        },
        {
            xtype: 'fieldset',
            title: 'IDs',
            collapsible: true,
            defaults:{
                xtype: 'textfield'
            },
            items:[
                {
                    name: 'id',
                    fieldLabel: 'ID',
                    readOnly: true,
                    bind: '{inventoryitem.id}'
                },
                {
                    name: 'brand_id',
                    fieldLabel: 'Brand ID',
                    readOnly: true,
                    bind: '{inventoryitem.brand_id}'
                }
            ]
        },
        {
            xtype: 'fieldset',
            title: 'Details',
            defaults:{
                xtype: 'textfield'
            },
            items:[
                {
                    name: 'name',
                    fieldLabel: 'Name',
                    bind: '{inventoryitem.name}'
                },
                {
                    name: 'price',
                    fieldLabel: 'Price',
                    bind: '{inventoryitem.price}'
                }
            ]
        }
    ]

});

我遇到的问题是,如果我单击一行以查看其详细信息(有效),然后单击New Item按钮,则在前一个详细信息面板上加载的记录仍会在新的详细信息面板上加载。

如果我New Item首先单击按钮,我会得到我要使用的空白表单,并且如果我选择不同的项目行,则所选行中的每条记录都会正确加载到详细信息面板中(这不是第一行的记录是“卡在详细信息面板中”),但是一旦我选择一行,该New Item按钮只会给我带有先前加载记录的表单。

在销毁和创建两个单独的视图/视图模型/视图控制器(或者我的控制器逻辑中是否存在我没​​有看到的缺陷)之间,是否有任何东西可以使指向视图模型的链接持续存在?

4

1 回答 1

0

如果您在详细信息的 viewModel 中唯一需要的是您尝试链接到的单个属性,请考虑根本不使用独立的 viewModel 来处理详细信息。

当您的详细信息面板位于inventory视图的项目中时,它实际上可以自然地访问视图的 viewModel(detailPanel.lookupViewModel()将返回组件树层次结构中最接近的单个 viewModel)。绑定也应该起作用。

但是,如果您需要一个单独的视图模型用于详细信息面板,您可以使用临时viewModel配置创建详细信息视图,该配置在实例化时合并到详细信息的视图模型中。

风景:

Ext.define('APP.view.TheView',{
    extend: "Ext.container.Container",
    alias: 'widget.theView',

    controller: 'theView',
    viewModel: { type: 'theView' },

    config: {
        detailConfig: { xtype: 'theDetail', reference: 'detail' }
    },

    items: ...
};

视图的视图控制器:

Ext.define('APP.controller.TheView',{
    extend: "Ext.app.ViewController",
    alias: 'controller.theView',

    onOpenDetail: function(){

        var detail = this.lookupReference('detail');

        if(!detail){

            var view = this.getView(),
                detailConfig = view.getDetailConfig(),
                theProperty = this.getViewModel().get('theProperty');

            detailConfig = Ext.apply({
                viewModel: {
                    // This actually gets correctly merged with whatever there is
                    // in the viewModel configuration of the detail
                    data: { theProperty: theProperty }
                }
            }, detailConfig));

            detail = view.add(detailConfig);
        }

        // Do something with the detail instance
    }
};

和细节:

Ext.define('APP.view.TheDetail',{
    extend: "Ext.panel.Panel",
    alias: 'widget.theDetail',

    controller: 'theDetail',
    viewModel: { type: 'theDetail' },

    items: ...
};

希望这有所帮助!:-)

于 2015-11-19T13:02:18.337 回答