0

I have this gridPanel:

Ext.define('BM.view.test.MacroList', {
extend: 'BM.view.GridPanel',
alias:'widget.macro-test-list',

store: 'Tests',

initComponent: function() {

    this.columns = [
        {
            xtype:'actioncolumn',
            width:50,
            items: [
            {
                icon: 'images/start.png',
                tooltip: 'Start Test',
                handler: function(grid, rowIndex, colIndex) {
                    this.application.fireEvent('testStart', grid.getStore().getAt(rowIndex)); 
                // application not defined here because 'this' is the button.
                }]
     }]
}
}

stratTest is a function that will be available from many places in the application, and I would like it to be used as an application wide event, but those seem to be available only from controllers.
How do I call .application.fireEvent('testStart'...) from the handler inside this button?

I'm using this question as a constant reference to events, and the Sencha docs, but couldn't find the answer.

Community
  • 1
  • 1
bldoron
  • 1,050
  • 4
  • 20
  • 37

3 Answers3

6

You get this.application within a controller scope.

Given you are clearly using MVC here, I'd say it's best to stick to MVC concepts; that is, for reusability sake, a component shouldn't know what controller uses it, but rather a controller should know what components it is using.

So you should really listen to the event in the controller, and fire an application event from there.

The problem is that there's no access to the actioncolumn handler from the controller (it is called internally in Ext.grid.column.Action processEvent()).

So your best shot is to fire a new event in the view:

this.columns = [
    {
        xtype:'actioncolumn',
        ...
        items: [
        {
            ...
            handler: function( aGrid, aRowIndex, aColIndex, aItem, aEvent, aRecord ) {
                this.fireEvent( 'columnaction', aGrid, aRowIndex, aColIndex, aItem, aEvent, aRecord); }
        }]
 }]

Notice also that you can define a global handler for the column, like so:

this.columns = [
    {
        xtype:'actioncolumn',

        handler: function( aGrid, aRowIndex, aColIndex, aItem, aEvent, aRecord ) {
            this.fireEvent( 'columnaction', aGrid, aRowIndex, aColIndex, aItem, aEvent, aRecord); }

        ...
        items: [
        {
            ...
        }]
 }]

And then catch this event in the controller.

init: function() {
    this.control({
        'macro-test-list actioncolumn':{
            columnaction: this.onAction
        }
    });
},

onAction: function( aGrid, aRowIndex, aColIndex, aItem, aEvent, aRecord ) {
    this.application.fireEvent( 'testStart', aGrid.getStore().getAt( aRowIndex ) );
}

Notice, by the way, that given what you are trying to do, a cleaner code would be:

onAction: function( aGrid, aRowIndex, aColIndex, aItem, aEvent, aRecord ) {
    this.application.fireEvent( 'testStart', aRecord );
}
Izhaki
  • 23,372
  • 9
  • 69
  • 107
  • This is a good answer, which I though of myself, but... It seems silly to me that I will listen to this event in the controller, send an application wide event which will then be caught on the controller. Isn't there another way? Also... Can't I somehow declare the scope of the controller to the button? – bldoron Sep 02 '12 at 10:48
  • 1
    Are there two controllers in question here? If you want to take advantage of the MVC patterns, the idea is (in ExtJs at least) that components fire events, and these are handled in the controllers. If the component code has anything to do with a specific controller, the component and its controller are now bound together and have to be used side-by-side. – Izhaki Sep 02 '12 at 10:57
  • Ok. I'll accept your answer then. One more quick one of you please...: If I have two items in the action column, how do I access them in the controller? as `'macro-test-list actioncolumn#id1'` gets nothing. – bldoron Sep 02 '12 at 11:11
  • You are best inspecting the `iItem` parameter of the click handler. – Izhaki Sep 02 '12 at 11:22
  • 1
    10x a million. You're are a true ExtJS guru. – bldoron Sep 02 '12 at 11:26
  • I've checked. This is not the parameter list that is passed to the listener. `onActionItemClick: function(iGrid, iRowIndex, iColIndex, iItem, iEvent, iRecord, a) { console.log(iGrid); console.log(iRowIndex); console.log(iColIndex); console.log(iItem); console.log(iEvent); console.log(iRecord); console.log(a); }` returns: gridView, cellEl, rowIndex, colIndex, event, record, rowEl I have no way of knowing which item was pressed. – bldoron Sep 02 '12 at 11:54
4

In terms of firing application-wide custom events, there is a new method now after ExtJS V5.1 is published, which is using Ext.GlobalEvents.

When you fire event, you do this:

Ext.GlobalEvents.fireEvent('custom_event',args); 

When you register a handler of the event, you do this:

var obj = Ext.create('Ext.form.Panel', {
  // ....
});
Ext.GlobalEvents.on('custom_event', function(arguments){
  /* handler codes*/
}, obj}; 

This method is not limited to controllers. Any component can handle a custom event through putting the component object as the input parameter scope.

Here is a fiddle.

gm2008
  • 4,245
  • 1
  • 36
  • 38
  • This is pretty awesome... it even disconnects the event for you when your class is destroyed. I was expecting there to be event bleeding and having to disconnect myself. – incutonez Sep 29 '15 at 15:36
0

APPNAME.getApplication.fireEvent() is available application-wide.