PDA

View Full Version : Catching bubbled events in controllers



jej2003
17 Jan 2012, 10:18 AM
I have a setup where I am bubbling events that I'd like to catch in my controller. I have something like this



this.control({
'mypanel': {
customevent : function(cmp){...}


where the customevent is bubbled up from a subcomponent of mypanel, but this doesn't get caught in the controller. If I do this



this.control({
'mypanel > subpanel': {
customevent : function(cmp){...}

it works fine. Also if I just add some listeners to make sure things are firing properly by doing


var myPanel = Ext.create('mypanel', {
listeners : {
customevent : function(){
alert('boo');
}
}
});

I see the method being called. Should this work?

mitchellsimoens
17 Jan 2012, 11:16 AM
I personally would go with 'mypanel > subpanel' or 'mypanel subpanel'. The event is firing only on the subpanel but bubbleEvents walks up the hierarchy to see if it has a listener.

jej2003
17 Jan 2012, 11:46 AM
hmm....so the problem is I don't know the type of the components that are being added, they are driven by dynamically created menu items. Does the component query support all sub classes? So if I said panel and my custom component was a subclass of panel would that work?

mitchellsimoens
17 Jan 2012, 11:50 AM
hmm....so the problem is I don't know the type of the components that are being added, they are driven by dynamically created menu items. Does the component query support all sub classes? So if I said panel and my custom component was a subclass of panel would that work?

Yes it will.

jej2003
17 Jan 2012, 1:09 PM
nevermind, had a dumb problem, looks like it works perfectly, thanks Mitchell

pao
19 Jan 2012, 12:16 PM
Then, this code works?



this.control({
'mypanel': {
customevent : function(cmp){...}
...


I have same problem, listeners don't catch bubbled events.

Any suggestion?

lorezyra
19 Jan 2012, 1:09 PM
check out the code I posted here to see how it works...

http://www.sencha.com/forum/showthread.php?175200-ExtJS-4.0.7-Bugs-Accordian

pao
19 Jan 2012, 2:09 PM
Sorry but i cannot see any bubbled event fired in your code.

My controller define this listener:


this.control({
'mypanel' : {
customevent : function(){...}
}
...

My panel has a child toolbar which contains a button. This button fires my customevent and bubbles up.


Ext.define('CustomToolbar' ,{
extend: 'Ext.toolbar.Toolbar',
alias : 'widget.customtoolbar',

initComponent: function() {
this.addEvents('customevent');
this.enableBubble('customevent');

// my button
var mybutton = new Ext.Button({
...
scope: this,
handler : function(){
this.fireEvent('customevent',this);
}
...
});
...



But mypanel customevent handler never is called. If i use selector 'mypanel customtoolbar' then it works. But it's not a solution for me.

lorezyra
19 Jan 2012, 2:43 PM
I recommend that you read up on how to use the component query feature... Seems like you need to properly define the events (as I did in my example code).

I suggest you read the API doc: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.app.Controller

pao
19 Jan 2012, 3:13 PM
my idea is to define custom events in toolbar (createclient, editclient, deleteclient). These events are fired by toolbar buttons on click event:

this.fireEvent('createclient',this)

And i'd like these events were handled by panel container. Using 'mypanel customtoolbar' selector it works, i know. But i want bubble my custom events and simply use 'mypanel' selector in controller.

Similar threads here (http://www.sencha.com/forum/showthread.php?135945-Bubble-custom-events-to-the-top&highlight=bubble), here (http://www.sencha.com/forum/showthread.php?152069-MVC-event-bubbling-bug-ot-is-it-just-me&highlight=bubble+controller) and here (http://www.sencha.com/forum/showthread.php?143362-When-is-it-appropriate-to-bubble-up-events-MVC-ExtJS-4&highlight=bubble)

Thanks!

lorezyra
21 Jan 2012, 3:46 PM
for application wide events, use



this.application.on({ //handle system-application wide events and calls here!!
'eventName1': this.event1Handler,
'eventName2': this.event2Handler,
'eventName3': this.event3Handler
});


this.control() is used only for the local controller. If you want the event bubbled up to the application level use this.application.on()

vietits
23 Jan 2012, 7:08 AM
The problem here is that <controller>.control() uses Ext.app.EventBus to inject the <component>.fireEvent() to catch events and this mechanism does not process the bubbled events.
I include here my way to resolve this problem. It overrides the Ext.app.EventBus.dispatch() method to catch both original events and bubbled events. This way, you can catch component events from its parents or its ancestors. One thing to remember is that this will only process original events and events that are enabled to bubble (set by enableBubble() method or bubbleEvents config).


Ext.define('Its.override.app.EventBus', {
override: 'Ext.app.EventBus',

dispatch: function(ev, target, args) {
var bus = this.bus,
selectors = bus[ev],
selector, controllers, id, i, ln,
events = target.events,
event = events && events[ev],
bubbles = event && event.bubble;


if (selectors) {
// Loop over all the selectors that are bound to this event
for (selector in selectors) {
// Check if the target matches the selector
// if(target.is(selector))
if (this.isSelectorTarget(target, selector, bubbles)) {
// Loop over all the controllers that are bound to this selector
controllers = selectors[selector];
for (id in controllers) {
// Loop over all the events that are bound to this selector on this controller
events = controllers[id];
for (i = 0, ln = events.length; i < ln; i++) {
event = events[i];
// Fire the event!
if (event.fire.apply(event, Array.prototype.slice.call(args, 1)) === false) {
return false;
};
}
}
}
}
}
},
isSelectorTarget: function(target, selector, bubbles) {
do {
if(target.is(selector)){
return true;
}
} while (bubbles && (target = target.getBubbleParent()));
return false;
}
});