-
22 Nov 2011 7:01 AM #1
Answered: MVC: Controller reference from Grid's Action Cell handler.
Answered: MVC: Controller reference from Grid's Action Cell handler.
How to get Controller's object reference from grid's actioncolumn's cell handler?
I have an application and have method defined in controller
I also add an actioncolumn like this in my grid:Code:Ext.define('myApp.controller.Users', { extend: 'Ext.app.Controller', ... myHandler: function(record) { // some cool code here } ... }
Code at red line does not work, because myApp var is not initialized properly yet while this piece of code is running.Code:{ ... some code for Grid ... columns: [ ... other columns ... { xtype: 'actioncolumn', items: [ { icon: 'edit_item.png', handler: function(grid, rowIndex, colIndex) { // trying to handle click var record = grid.getStore().getAt(rowIndex); // Now I need a reference to my Users controller of application! myApp.controller.Users.myHandler(record) // does not work } } ] } ...
I need a proper way to reference Controller object (or Application object) at this piece of column-configuration code.
-
Best Answer Posted by tobiu
hi dennis,
action columns have the method:
so they listen to click events already (fetching it from the gridView to be more precise). i would try to listen to this event directly. if that is not possible in a way you need it, it would possibly override this method to fire the event manually there.Code:/** * @private * Process and refire events routed from the GridView's processEvent method. * Also fires any configured click handlers. By default, cancels the mousedown event to prevent selection. * Returns the event handler's status to allow canceling of GridView's bubbling process. */ processEvent : function(type, view, cell, recordIndex, cellIndex, e){ var me = this, match = e.getTarget().className.match(me.actionIdRe), item, fn; if (match) { item = me.items[parseInt(match[1], 10)]; if (item) { if (type == 'click') { fn = item.handler || me.handler; if (fn && !item.disabled) { fn.call(item.scope || me.scope || me, view, recordIndex, cellIndex, item, e); } } else if (type == 'mousedown' && item.stopSelection !== false) { return false; } } } return me.callParent(arguments); }
well, your approach also gets the job done, so i see no problem in keeping it this way. if you have many action columns in different modules, you might be feeling more comfortable with the "generic" override, since it saves some boiler plate code in that case.
it might be worth a try to add a feature request for the event "actionClicked".
-
22 Nov 2011 7:49 AM #2Sencha - Services Team
- Join Date
- May 2007
- Location
- Munich (Germany)
- Posts
- 2,292
- Vote Rating
- 6
- Answers
- 56
imho this is not the best approach.
the MVC is not meant to have controllers with a collection of methods and views with handlers directly calling the controller.
the idea is, that the controller listens for view events itself and calls its own methods then.
take a look at ComponentQuery to see how to identify view elements and events to listen to:
http://docs.sencha.com/ext-js/4-0/#!...ComponentQuery
and also into the controller definitions:
http://docs.sencha.com/ext-js/4-0/#!...app.Controller
like:
Code:Ext.define('MyApp.controller.Users', { extend: 'Ext.app.Controller', init: function() { this.control({ 'viewport > panel': { render: this.onPanelRendered } }); }, onPanelRendered: function() { console.log('The panel was rendered'); } });
-
23 Nov 2011 3:27 AM #3
Thanks, tobiu
But in my case it's probably better to fire some custom event during click on action columns action button like this:
And after that i can listen to this myCustomEventMeaningClickOnAction in controller ...Code:... handler: function(grid, rowIndex, colIndex) { var record = grid.getStore().getAt(rowIndex); this.fireEvent('myCustomEventMeaningClickOnAction', this, record); }
Is it ok from designing app point of view?
-
23 Nov 2011 4:14 AM #4Sencha - Services Team
- Join Date
- May 2007
- Location
- Munich (Germany)
- Posts
- 2,292
- Vote Rating
- 6
- Answers
- 56
hi dennis,
action columns have the method:
so they listen to click events already (fetching it from the gridView to be more precise). i would try to listen to this event directly. if that is not possible in a way you need it, it would possibly override this method to fire the event manually there.Code:/** * @private * Process and refire events routed from the GridView's processEvent method. * Also fires any configured click handlers. By default, cancels the mousedown event to prevent selection. * Returns the event handler's status to allow canceling of GridView's bubbling process. */ processEvent : function(type, view, cell, recordIndex, cellIndex, e){ var me = this, match = e.getTarget().className.match(me.actionIdRe), item, fn; if (match) { item = me.items[parseInt(match[1], 10)]; if (item) { if (type == 'click') { fn = item.handler || me.handler; if (fn && !item.disabled) { fn.call(item.scope || me.scope || me, view, recordIndex, cellIndex, item, e); } } else if (type == 'mousedown' && item.stopSelection !== false) { return false; } } } return me.callParent(arguments); }
well, your approach also gets the job done, so i see no problem in keeping it this way. if you have many action columns in different modules, you might be feeling more comfortable with the "generic" override, since it saves some boiler plate code in that case.
it might be worth a try to add a feature request for the event "actionClicked".
-
23 Nov 2011 4:20 AM #5
well ... my main problem is getting those action columns objects from controller's control method (via Ext.ComponentQuery) using some approach like assigning some CSS class to them and after that trying to work with classnames.
For now it's easier for me to fire custom events in all my views/components objects and have just one listener in Controller object. But approach of having list of objects to be listened in Controller works too ...
Thanks again


Reply With Quote