扩展ExtJS 4 MVC应用程序中的控制器

时间:2012-03-02 17:56:02

标签: extjs4 extjs-mvc

我按照MVC结构构建我的ExtJS 4应用程序。我想制作一个可扩展的网格MyGrid,它具有一些我可以重复使用的功能。因此,我猜,它应该有自己的控制器,它也是扩展的,因此功能是继承的。这怎么做得好?

在下面的代码中,我将说明如何使用MyExtendedGrid扩展控制器MyGrid。我意识到我正在覆盖MyGrid控制器中的 init 函数,因此永远不会调用它。问题是通过从MyExtendedGrid init 调用MyGrid中的“super” init ,还是合并控件对象来解决?这是在MVC精神中这样做的正确方法吗?如果是这样,怎么样?

controller / MyGrid.js:

Ext.define('App.controller.MyGrid', {
    extend: 'Ext.app.Controller',
    refs: [
        {
            ref: 'myGridView',
            selector: 'mygrid'
        }
    ],
    init: function() {
        var me=this;
        me.control({
            'mygrid textfield[name=searchField]': {
                change: function() {
                    var view = me.getMyGridView();
                    // Do something with view
                }
            }
        });
    }
});

controller / MyExtendedGrid.js:

Ext.define('App.controller.MyExtendedGrid', {
    extend: 'App.controller.MyGrid',
    views: [
        'grids.MyExtendedGrid'],
    refs: [
        {
            ref: 'myExtendedGridView',
            selector: 'myextendedgrid'
        }
    ],
    init: function() {
        var me=this;
        me.control({
            'myextendedgrid': {
                // Some control code
                // Using getMyExtendedGridView()
            }
        });
    }
});

view / grids / MyGrid.js:

Ext.define('App.view.grids.MyGrid', {
    extend: 'Ext.grid.Panel',
    alias : 'widget.mygrid',
    requires: [
    ],
    store: '', // Not defined here
    columns: [ ], // Not defined here

    initComponent: function() {
        var me = this;
        me.tbar = [
            'Search',
            {
                 xtype: 'textfield',
                 name: 'searchField',
                 hideLabel: true,
                 width: 150
            }
        ];
        me.callParent(arguments);
    }
});

view / grid / MyExtendedGrid.js:

Ext.define('App.view.grids.MyExtendedGrid', {
    extend: 'App.view.grids.MyGrid',
    alias : 'widget.myextendedgrid',
    store: 'MyStore',
    columns: [
        // ...
    ],

    initComponent: function() {
        var me = this;
        me.bbar = [
            //...
        ];
        me.callParent(arguments);
    }
});

2 个答案:

答案 0 :(得分:1)

实际上有点棘手......

以下是我们在应用程序中所做的事情(我们有完全相同的情况 - 某种基本控制器,可以在许多不同的地方重复使用)

  1. 在基本控制器中保留init函数。

  2. 在此基本控制器中定义公共基本方法(如gridRendered - 您需要始终为所有控制器执行某些操作)。

  3. 订阅所有子控制器中的事件,但使用基本控制器的方法订阅事件。它不会起作用 - 基本控制器没有适当的参考来正确订阅事件。

  4. 我可以发布几个源代码片段,但我认为它非常简单。

答案 1 :(得分:1)

好的,经过一番思考后我决定使用以下解决方案,其优点是mygrid不需要了解myextendedgrid。

我在问题中扩展了gridview。

我为基本网格提供了自己的控制器来执行常用功能,例如在网格中选择了某些内容时deleteButton.setDisable(false)

接下来,我提醒自己使用refs:[(例如使用selector: 'mygrid')会模糊地指向基类的任何扩展实例的两个实例。使用me.control({时,我会使用up遍历激活的元素来获取相关网格:

me.control({
    'mygrid textfield[name=searchField]': {
        change: function(searchfield) {
            var grid=searchfield.up('mygrid'); // (mygrid or myextendedgrid!)
            // Do something with view
        }
    }
...

扩展网格我给它自己的控制器,在这里我可以使用refs。我不会从MyGrid类扩展控制器(而是从'Ext.app.Controller'扩展),除非我想使用MyGrid控制器中的函数或变量。所有控制器都是使用以下命令从app.js启动的:

Ext.application({
    controllers: [
        'MyGrid'
        'MyExtendedGrid',
    ],
...

为了在网格中选择行时获取网格,我将网格存储在选择模型中,如下所示:

在controller / MyGrid.js中:

me.control({
    'mygrid': {
        afterrender: function(grid) {
            var selModel=grid.getSelectionModel();
            selModel.myGrid=grid;
        },
        selectionchange: function(selModel, selected, eOpts) {
            var grid=selModel.theLookupGrid;
            // Do something with view
        }
...