Расширение контроллера в приложении ExtJS 4 MVC

Я создаю свое приложение ExtJS 4, следуя структуре MVC. Я хочу сделать расширяемую сетку MyGrid с некоторыми функциями, которые я могу использовать несколько раз. Поэтому, я думаю, у него должен быть свой собственный контроллер, который также расширяется, чтобы функциональность наследовалась. Как это правильно делается?

В приведенном ниже коде показано, как я расширяю контроллер MyGrid с помощью MyExtendedGrid. Я понимаю, что переопределяю функцию init в контроллере MyGrid, чтобы она никогда не вызывалась. Проблема решается простым вызовом «супер» init в MyGrid из MyExtendedGrid init или объединением объектов control? Это правильный способ сделать это в духе MVC? Если да, то как?

контроллер/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
                }
            }
        });
    }
});

контроллер/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()
            }
        });
    }
});

вид/сетки/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);
    }
});

вид/сетки/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);
    }
});

person Louis    schedule 02.03.2012    source источник


Ответы (2)


На самом деле немного сложнее...

Вот что мы сделали в нашем приложении (у нас точно такая же ситуация - какой-то базовый контроллер, который повторно используется во многих разных местах)

  1. Сохраните функцию инициализации в базовом контроллере.

  2. Определите общий базовый метод в этом базовом контроллере (например, gridRendered, где вам нужно постоянно что-то делать для всех контроллеров).

  3. Подпишитесь на события во всех дочерних контроллерах, но подписывайтесь на события, используя методы базового контроллера. В противном случае это не сработает - базовый контроллер не имеет правильных ссылок для правильной подписки на события.

Я могу опубликовать пару фрагментов исходного кода, но я думаю, что это довольно просто.

person sha    schedule 02.03.2012
comment
@sha Мне бы очень понравилось, если бы вы опубликовали фрагмент кода или два. - person Levi Hackwith; 09.03.2012
comment
@LeviHackwith: нет проблем. давайте сделаем это в отдельном вопросе, чтобы не путать этот. хочешь опубликовать новый вопрос? - person sha; 09.03.2012
comment
@sha Я искал фрагмент кода, связанный с вашим решением. Вы все еще думаете, что это должно быть в отдельном вопросе? Мне просто трудно визуализировать шаги, которые вы перечисляете. - person Levi Hackwith; 09.03.2012
comment
@LeviHackwith Я думаю, что это будет меньше сбивать с толку других людей, потому что мой ответ больше не помечен как ответ ... Похоже, автор темы нашел другой способ - person sha; 09.03.2012
comment
@sha stackoverflow. com/questions/9628306/ - person Levi Hackwith; 09.03.2012

Хорошо, после некоторого размышления я выбрал следующее решение, преимущество которого в том, что mygrid не нужно знать о myextendedgrid.

Я расширяю свой вид сетки, как в вопросе.

Я дал базовой сетке собственный контроллер для выполнения общих функций, например, 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',
    ],
...

Чтобы получить сетку при выборе строк в сетке, я сохранил сетку в модели выбора, как показано ниже:

В контроллере/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
        }
...
person Louis    schedule 08.03.2012