Расширение контроллера в приложении ExtJS 4 MVC
Я строю свое приложение ExtJS 4, следуя структуре MVC. Я хочу создать расширяемую сетку MyGrid с некоторыми функциями, которые я могу использовать несколько раз. Поэтому, я думаю, он должен иметь свой собственный контроллер, который также расширен, чтобы функциональность была унаследована. Как это правильно сделать?
В приведенном ниже коде я иллюстрирую, как я расширяю контроллер MyGrid с помощью MyExtendedGrid. Я понимаю, что переопределяю функцию init в контроллере MyGrid, так что она никогда не вызывается. Проблема решается просто вызовом "super" init в MyGrid из MyExtendedGrid 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 / grids / 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 ответа
Хорошо, после некоторых размышлений я выбрал следующее решение, которое имеет то преимущество, что 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',
],
...
Чтобы получить сетку, когда в сетке выбраны строки, я сохранил сетку в модели выбора, как показано ниже:
В контроллере /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
}
...
Это на самом деле немного сложнее...
Вот что мы сделали в нашем приложении (у нас точно такая же ситуация - некий базовый контроллер, который используется во многих местах)
Сохраните функцию инициализации в базовом контроллере.
Определите общий базовый метод в этом базовом контроллере (например, gridRendered - где вам нужно все время что-то делать для всех контроллеров).
Подписаться на события во всех дочерних контроллерах, но подписаться на события, используя методы базового контроллера. В противном случае это не будет работать - базовый контроллер не имеет надлежащих ссылок для правильной подписки на события.
Я могу опубликовать несколько фрагментов исходного кода, но я думаю, что это довольно просто.