看起来像ViewModel在它的视图在extjs中被销毁后仍然存在

时间:2015-10-13 12:31:52

标签: extjs mvvm extjs6

我确定我在这里找不到的东西,我只是看不出它是什么。

我有演示项目我在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' },
            ]
        }
    ]
});

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

这是列表的控制器:

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按钮,我会得到空白表单,如果我选择不同的项目行,则所选行中的每个记录都会正确加载到详细信息面板中(&# 39;不是第一行的记录在详细信息面板中被卡住了#34;但是只要我选择一行,New Item按钮只会给我一个表格先前加载的记录。

在销毁和创建两个独立的视图/视图模型/视图控制器之间是否会存在一个链接到视图模型的链接(或者我的控制器逻辑中是否存在我只是没有看到的缺陷)?

1 个答案:

答案 0 :(得分:0)

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

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

但是,如果您需要为详细信息面板使用单独的viewModel,则可以使用ad-hoc 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: ...
};

view的viewController:

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: ...
};

希望这会有所帮助! : - )