PDA

View Full Version : MVC: How to listen to one common event from multiple views?



karan
9 Oct 2012, 4:51 AM
Our app has one function (the Fav button) that is on all views. This is exactly like the 'Like' button on FB which is everywhere. Whenever this button is pressed, I'd like to emit a custom event with the ID of the item being fav'ed.

A single piece of event handler code should handle this. My question is where do I put this code in my MVC app? Seems like controllers listen to events only from the views they control. Would it force me to have on controller that controls all views and listens to this one event? Or is there a better way?

Gracias

mitchellsimoens
9 Oct 2012, 5:11 AM
Moved to Ext JS 4 Q&A forum as appropriate.

vietits
9 Oct 2012, 5:17 AM
You should put your code in controller. Controller will listen to registered events from all components in your application provided that they are matched the selector.

ljparra
9 Oct 2012, 12:53 PM
I have a similar question, surely same answer, I need listen clicks on all link tags, Ext.addBehaviors (http://docs.sencha.com/ext-js/4-0/#%21/api/Ext-method-addBehaviors) works well with current links but how to listen the new ones created dinamically ? (I think calling this function every time is not a good practice)

ljparra
9 Oct 2012, 1:26 PM
A workaround was listen click on body and check for href attribute:



Ext.getBody().on('click', function(event, target){
console.log(target.attributes['href'].value);
event.preventDefault();
})

karan
9 Oct 2012, 7:30 PM
@Vietits:
Can you please elaborate on your answer? The problem I have is that multiple views, and multiple components from those views, from different parts of the application are throwing this one event. In this case, one controller will have to define refs to multiple components and also define "this.control" for each specific component as the code below does for grid and button below.


refs:[{ref:'list', selector:'grid'}], init:function(){this.control({'button':{ click:this.refreshGrid }});}, refreshGrid:function(){this.getList().store.load();}

My problem is this wont scale. This is ok for 1 or 2 or even 10 components for which control is defined. How do you scale it to 50? As I said, compare it to the Like action on facebook. It's all over the place. Almost all components in our app will have this button.

Thats why I asked whether I can just listen to one named event centrally somewhere? No matter who threw it, 1 controller/class should be able to catch and handle it. Whats the best pattern for that?

@ljparra : I agree that worst case you can let the event bubble to the body and listen to it. That kind of defeats the purpose of MVC and all the massive abstraction that ext provides. In my opinion, if I'm doing that, then why do MVC at all? Why not go back to developing pages/apps like we used to?

ljparra
9 Oct 2012, 7:55 PM
I create a controller only for this task, made this test and work for me:


//FavButtonController.js
Ext.define('MyApp.controller.FavButtonController',{
extend: 'Ext.app.Controller',

init: function(){
this.control({
'button[action=fav]': {
click: this.favButtonHandler
}
});
},

favButtonHandler: function(){
console.log('favButtonHandler');
}
});

and added this controller to app

//app.js
controllers: [..., 'FavButtonController']

then in the views you can add the buttons

//MyView.js
{
xtype: 'button',
text: 'Favorite',
action: 'fav'
}

vietits
9 Oct 2012, 8:20 PM
Hi Karan,

You can refer to ljparra's solution in post #7. This is what I mean in my previous post.

karan
9 Oct 2012, 8:40 PM
Thanks Guys.

This seems to be the right solution. I'll give it a try and get back.

One related question: How do I update the count back on the button? Should the button pass it's id as a part of the event?

vietits
9 Oct 2012, 10:21 PM
With click event on button, the first argument passed to event handler is the button itself. See more information here http://docs.sencha.com/ext-js/4-1/#!/api/Ext.button.Button-event-click