6

I have a Panel and I need to capture/handle the mouseover event for the element of this panel.

Currently I do this by extending the ExtJS Panel with the following listener (as suggested here):

...

listeners: {
    mouseover : {
        element : 'el',
        fn : function(){
            console.log('captured mouseover');
        }
    }
},

...

Can it be done via the ExtJS controller? So that I have the event handling in one controller?

Joseph Victor Zammit
  • 14,760
  • 10
  • 76
  • 102
  • possible duplicate of [Attach ExtJS MVC controllers to DOM elements, not components](http://stackoverflow.com/questions/6047862/attach-extjs-mvc-controllers-to-dom-elements-not-components) – AndreKR Nov 08 '12 at 14:00

4 Answers4

8

You're on the right track, just not completely there yet. Controller's job is to control components not elements. If you want to make element's mouseover event to be available at the component level, just refire it as distinct 'mypanelmouseover' event and use that in Controller's control().
Nice and neat.

EDIT:

Here's how to do it:

Ext.define('My.Panel', {
    extend: 'Ext.panel.Panel',

    constructor: function(config) {
        var me = this;

        me.callParent(arguments);

        me.addEvents(
            'mypanelmouseover'
        );
    },

    afterRender: function() {
        var me = this;

        me.callParent();

        // Declarative style with listeners reads better,
        // but this is shorter and does the same
        me.mon(me.getEl(), 'mouseover', function() {
            this.fireEvent('mypanelmouseover')
        }, me);
    }
});

Ext.define('My.Controller', {
    extend: 'Ext.app.Controller',

    init: function() {
        var me = this;

        me.control({
            'panel': {
                mypanelmouseover: me.onMyPanelMouseover
            }
        });
    }
});

Hope this helps. The main idea is to keep being declarative and decouple your code instead of creating unreadable callback chain. A nice side effect is that you're in control and can decide which events you want to refire and when, and how to react to them.

Alex Tokarev
  • 4,821
  • 1
  • 20
  • 30
  • Thanks, how to fire "mypanelmouseover"? Using [`fireEvent`](http://docs.sencha.com/ext-js/4-1/#!/api/Ext.util.Observable-method-fireEvent)? And can I come up with any event name I like? And "refire it", on what? The component is not available in that particular event hanlder. – Joseph Victor Zammit Aug 13 '12 at 20:35
  • Good idea, but have moved on using @NeilMcGuigan's answer, which is very similar, but with the code. +1ed your answer. – Joseph Victor Zammit Aug 13 '12 at 20:48
  • 1
    Neil's answer is, in fact, very different. I'll post a code snippet to better illustrate what I mean. – Alex Tokarev Aug 13 '12 at 21:15
  • Also, it's not like I'm bashing anyone but I would strongly suggest not to go the route Neil has suggested. The land of many pain lies there, and next time you'll have to refactor your code due to external changes (like in Ext JS) you'll curse yourself for the callback chains you've created. I know, I've been there. – Alex Tokarev Aug 13 '12 at 21:31
  • What is happening at the 3 lines starting with line `me.mon(me.getEl(), function() {` ? – Joseph Victor Zammit Aug 17 '12 at 16:29
  • 1
    me.getEl() returns Ext.Element instance that incapsulates main DOM element for this Component (usually
    ). me.mon() attaches managed listener to that Element, an anonymous function (second arg) that will be executed in me/this scope (third arg). Managed listener means it will be destroyed automatically when Component is destroyed.
    – Alex Tokarev Aug 17 '12 at 17:25
4

You could attach the listener after the component renders:

Ext.define('My.controller.A', {
    extend:'Ext.app.Controller',

    init: function(){ 
        this.control({
            'panel1':{
                afterrender: function(cmp){
                    cmp.getEl().on('mouseover', this.panel1_mouseOver);
                }
            }
        });
    },

    panel1_mouseOver: function(e, t, eOpts){
        alert('mouseover');
    }
});
Neil McGuigan
  • 46,580
  • 12
  • 123
  • 152
2

I think the only way to add that feature is to change the library's source for the Panel component. I don't think this is a good idea because it'll probably slow your site down with all the extra listeners, but this is how you'd do it.

http://docs.sencha.com/ext-js/4-1/source/Panel.html#Ext-panel-Panel Look for "me.addEvents" to see the events that ExtJS decided to give access to. You could add the mouseover event there, then add the listener in the controller.

What exactly are you doing for that listener? If you are just adding a class to the panel's div element then you could just use the overCls config http://docs.sencha.com/ext-js/4-1/#!/api/Ext.AbstractComponent-cfg-overCls

It looks like there are only a few components that support the mouseover event. Would it be possible to separate this mouse over functionality into a menu or button component?

sissonb
  • 3,730
  • 4
  • 27
  • 54
1

Every component has "getEl" method. Use this method to get Dom element and then register event on it.

Neil McGuigan
  • 46,580
  • 12
  • 123
  • 152
MAP
  • 34
  • 3