EventHandling in GWT with LayoutPanels - events

I have some questions regarding GWT (2.1) with MVP and events.
Got DockLayoutPanel with some components in it. A Tree component to the west and a SimplePanel in center. Each component has a presenter and a view. The problem is that I want to handle the components events in their presenter class, but now they are only catchable in the container which is the DockLayoutPanelPresenter . I want to handle the tree's event s in the TreePresenter. I think that the TreePresenter should handle its 'SelectedItem' events and the it can put it on the eventbus so that my other components can react to it.
Has anyone else faced this? Posted on GWT groups list, but got no reply. I think this is an imporant topic for decoupling components.

In this case, where different regions of the page each have a Presenter, you could use the approach suggested by David Chandler of the GWT team:
http://groups.google.com/group/google-web-toolkit/browse_thread/thread/2812e1b15a2a98a6/8c82d629b7a48e56?lnk=gst&q=EastActivityMapper#8c82d629b7a48e56
You should read the post, but in summary, you would do something like this:
WestActivityMapper westActivityMapper = new WestActivityMapper();
WestActivityManager westActivityManager = new WestActivityManager(westActivityMapper, eventBus);
westActivityManager.setDisplay(westPanel);
EastActivityMapper EastActivityMapper = new EastActivityMapper();
EastActivityManager eastActivityManager = new EastActivityManager(eastActivityMapper, eventBus);
EastActivityManager.setDisplay(eastPanel);
dockLayoutPanel.addWest(westWidget, 50);
dockLayoutPanel.addEast(eastWidget, 50);
RootLayoutPanel.get().add(dockLayoutPanel);
The west activity mapper would be responsible for displaying your Tree, and the east mapper would contain the body of your application.
We are using this approach to display a list of items in our west docked panel (not a tree, but close enough) which then updates what is displayed in the body of our app. When a user selects an item from the list we trigger a new Place event, and include the list item's id as the Place Token, so that the user can use the back button. However, you could also use the EventBus as you pointed out.

Related

How to apply a central dispatcher among multiple views with Backbone.js?

I am using a Backbone.js app with a central dispatcher and central view called AppView.
In an initializer, I declare the central dispatcher with:
this.dispatcher = _.extend({}, Backbone.Events);
This dispatcher is passed to every view the app has. Each one can trigger and/or bind to custom events for this dispatcher. In this way, I pretend to allow communication between views without having references to nested views / etc.
My issue is:
If I have several views listening for the same event, when the x event is triggered by someone, all of those views can respond to it. My problem is: Depending of the context (flow) of the application, not all of the listeners should react to that event...
Any workaround? Am I doing something wrong from what a central dispatcher should be?
Thanks!
I think you may need "Mediator", It will broadcast event and your custom event to every views that subscribe it.
I recently face with a similar situation and looking for solutions I found differents solutions:
Using a central event dispatcher which is shared by all the models and views. I get with this solutions in this interesting post:
http://www.michikono.com/2012/01/11/adding-a-centralized-event-dispatcher-on-backbone-js/
Make the dispatcher natively accesible for all the models and views as it is developed in this post:
http://devlicio.us/blogs/mike_nichols/archive/2011/10/20/backbone-events-and-aggregator-update.aspx
From my experience, to maintain in good shape the code it is worth to avoid using central dispatchers. We create a set of dispatchers for every module of the app (each module can contain differents views that need to communicate each one):
var searchTabEvents = _.extend({}, Backbone.Events); //handler events for the search tab
var visualizationEvents = _.extend({}, Backbone.Events); //handler events for the visualization tab
And when we create the views we pass to the view the appropiatte event handler:
var extEvents = searchTabEvents;
var searchView = new SearchView({customEvents : extEvents});

Is Ext JS's MVC an anti-pattern?

I work in a team of 25 developers. We use ExtJS MVC pattern of Sencha. But we believe that their definition of MVC is misleading. Maybe we might call their MVC an anti-pattern too.
AMAIK, in MVC controller only knows the name or the path of the view, and has no knowledge on the view's internal structure. For example, it's not the responsibility of the controller, whether view renders the list of customers a simple drop down, or an auto-complete.
However, in Ext JS's MVC, controller should know the rendering of view's elements, because controller hooks into those elements, and listens to their events. This means that if an element of the view change (for example a button become a link), then the relevant selector in the controller should change too. In other words, controller is tightly-coupled to the internal structure of the view.
Is this reason acceptable to denounce Ext JS's MVC as anti-pattern? Are we right that controllers are coupled to views?
UPDATE (March 2015): Ext 5.0 introduced ViewControllers that should address most of the concerns discussed in this thread. Advantages:
Better/enforced scope around component references inside the ViewController
Easier to encapsulate view-specific logic separately from application flow-control logic
ViewController lifecycle managed by the framework along with the view it's associated with
Ext 5 still offers the existing Ext.app.Controller class, to keep things backwards-compatible, and to give more flexibility for how to structure your application.
Original answer:
in Ext JS's MVC, controller should know the rendering of view's elements, because controller hooks into those elements, and listens to their events. This means that if an element of the view change (for example a button become a link), then the relevant selector in the controller should change too. In other words, controller is tightly-coupled to the internal structure of the view.
I actually agree that in most cases this is not the best choice for the exact reasons you cite, and it's unfortunate that most of the examples that ship with Ext and Touch demonstrate refs and control functions that are often defined using selectors that violate view encapsulation. However, this is not a requirement of MVC -- it's just how the examples have been implemented, and it's easy to avoid.
BTW, I think it definitely can make sense to differentiate controller styles between true application controllers (control app flow and shared business logic, should be totally uncoupled from views -- these are what you're referring to), and view controllers (control/event logic specific to a view, tightly-coupled by design). Example of the latter would be logic to coordinate between widgets within a view, totally internally to that view. This is a common use case, and coupling a view-controller to its view is not an issue -- it's simply a code management strategy to keep the view class as dumb as possible.
The problem is that in most documented examples, every controller simply references whatever it wants to, and that's not a great pattern. However, this is NOT a requirement of Ext's MVC implementation -- it is simply a (lazy?) convention used in their examples. It's quite simple (and I would argue advisable) to instead have your view classes define their own custom getters and events for anything that should be exposed to application controllers. The refs config is just a shorthand -- you can always call something like myView.getSomeReference() yourself, and allow the view to dictate what gets returned. Instead of this.control('some > view > widget') just define a custom event on the view and do this.control('myevent') when that widget does something the controller needs to know about. Easy as that.
The drawback is that this approach requires a little more code, and for simple cases (like examples) it can be overkill. But I agree that for real applications, or any shared development, it's a much better approach.
So yes, binding app-level controllers to internal view controls is, in itself, an anti-pattern. But Ext's MVC does not require it, and it's very simple to avoid doing it yourself.
I use ExtJS 4's MVC everyday. Rather than spaghetti code, I have an elegant MVC app that has tightly defined separation of concens and is ridiculously simple to maintain and extend. Maybe your implementation needs to be tweaked a bit to take full advantage of what the MVC approach offers.
Of course the controllers are bound to the views in some way. You need to target exactly which elements in your views you want to listen to.
eg: listen to that button clicks or to that form element change or to that custom component/event.
The goal of MVC is components decoupling and reusability and the Sencha MVC is awesome for that. As #bmoeskau says, you have to be careful in separation of the view controllers (builtin for the view/widgets itself) and the application controllers (top level views manipulations) to take full advantage of the MVC pattern. And this is something not obvious when your read http://docs.sencha.com/ext-js/4-1/#!/guide/application_architecture. Refactor your MVC approach, create different controllers, create custom component, and embrace the full ExtJS MVC architecture to take advantage of it.
There's still a slight problem in Sencha approach IMHO, the MVC refs system doesnt really work when you have multiple instances of the same views in an Application. eg: if you have a TabPanel with multiple instances of the same Component, the refs system is broken as it will always target the first element found in the DOM... There are workarounds and a project trying to fix that but i hope this will be adressed soon.
I'm currently undergoing the Fast Track to ExtJS 4 from Sencha Training. I have a strong background in ExtJS (since ExtJS 2.0) and was very curious to see how the MVC was implemented in ExtJS 4.
Now, previously, the way I would simulate kind of a Controller, would be to delegate that responsibility to the Main Container. Imagine the following example in ExtJS 3:
Ext.ns('Test');
Test.MainPanel = Ext.extend(Ext.Container, {
initComponent : function() {
this.panel1 = new Test.Panel1({
listeners: {
firstButtonPressed: function(){
this.panel2.addSomething();
},
scope: this
}
});
this.panel2 = new Test.Panel2();
this.items = [this.panel1,this.panel2];
Test.MainPanel.superclass.initComponent.call(this);
}
});
Test.Panel1 = Ext.extend(Ext.Panel, {
initComponent : function() {
this.addEvents('firstButtonPressed');
this.tbar = new Ext.Toolbar({
items: [{
text: 'First Button',
handler: function(){
this.fireEvent('firstButtonPressed');
}
}]
});
Text.Panel1.superclass.initComponent.call(this);
}
});
Test.Panel2 = Ext.extend(Ext.Panel, {
initComponent : function() {
this.items = [new Ext.form.Label('test Label')]
Test.Panel2.superclass.initComponent.call(this);
},
addSomething: function(){
alert('add something reached')
}
});
As you can see, my MainPanel is (besides the fact that is holding both panels) also delegating events and thus creating a communication between the two components, so simulating sort of Controller.
In ExtJS 4 there is MVC directly implemented in it. What really striked me was that the way the Controller actually fetches the components is through QuerySelector which in my opinion is very prone to error. Let's see:
Ext.define('MyApp.controller.Earmarks', {
extend:'Ext.app.Controller',
views:['earmark.Chart'],
init:function () {
this.control({
'earmarkchart > toolbar > button':{
click:this.onChartSelect
},
'earmarkchart tool[type=gear]':{
click:this.selectChart
}
});
}
});
So as we can see here, the way the Controller is aware of the earmarkchart button and tool is through selectors. Let's imagine now that I am changing the layout in my earmarkchart and I actually move the button outside of the toolbar. All of a sudden my application is broken, because I always need to be aware that changing the layout might have impact on the Controller associated with it.
One might say that I can then use itemId instead, but again I need to be aware if I delete a component I will need to scatter to find if there is any hidden reference in my Controllers for that itemId, and also the fact that I cannot have the same itemId per parent Component, so if I have an itemId called 'testId' in a Panel1 and the same in a Grid1 then I would still need to select if I want the itemId from Panel1 or from the Grid1.
I understand that the Query is very powerful because it gives you a lot of flexibility, but that flexibility comes at a very high price in my opinion, and if I have a team of 5 people developing User Interfaces and I need to explain this concepts I will put my hands on the fire that they will make tons of mistakes because of the points I referenced before.
What's your overall opinion on this? Would it be easier to just somehow communicate with events? Meaning if my Controller is actually aware of what views he's expecting events, then one could just fire an event dosomethingController and the associated Controller would get it, instead of all this Query problem.
I think if you use the Sencha Architect to produce the Views then Inherit from that View to create Your own View.
Now this View Can be responsible to hook up to any events and raise meaningful events.
This is just a thought...
//Designer Generated
Ext.define('MyApp.view.MainView', {
extend: 'Ext.grid.GridPanel',
alias: 'widget.mainview',
initComponent: function() {
}
});
//Your View Decorator
Ext.define('MyApp.view.MainView', {
extend: 'MyApp.view.MainViewEx',
alias: 'widget.mainviewex',
initComponent: function() {
this.mon(this, 'rowselect', function(){
this.fireEvent('userselected', arguments);
}, this);
}
});
I think there is a pretty bad problem here - its very difficult to shard isolated units within a page.
The approach I'm experimenting with (which makes it somewhat easier to write tests aswell) is to have a vanilla js context object for each page which contains the logic (and has the benefit of being very easy to break up and delegate to different objects). The controllers then basically call methods on the context objects when they receive events and have methods on them for retrieving bits of the view or making changes to the view.
I'm from a wpf background and like to think of the controllers as code-behind files. The dialog between presenter/context and view is a lot chattier than wpf (since you dont have binding + data templating) but its not too bad.
Theres also a further problem I haven't had to solve yet - the use of singletons for controllers causes problems for reuse of UI elements on the same page. That seems like a serious design flaw. The common solution I've seen is (yet again) to pile everything into one file and in this case to ditch the controller altogether. Clearly that's not a good approach as soon as things start to get complicated.
It seems like getting all the state out of the controller should help though and you'd then have a second level of context objects - the top level one would basically just assign a unique id to each view and have a map of context=>view and provide dispatch to the individual context methods - it'd basically be a facade. Then the state for each view would be dealt with in the objects dispatched to. A good example of why statics are evil!

Prism navigation- finding out origin of navigation request?

I have a viewmodel tied to a view used in a region. I'm trying to find a way that when that view is navigated to from a particular view (say view A), it does some work internally, like initializing some lists, setting some stuff, whatever. But if it has been navigated to from view B, it needs to NOT reinitialize everything, and just display the data it already has.
I could pass a parameter I suppose, saying whether this is a new operation or if we are going back to work on the old one, but I thought it would be nicer to be able to state that if we came from this view, we do one thing, and if we came from that one we do another.
If that makes sense :)
You can implement the INavigationAware interface which contains 3 methods. One of these methods is the OnNavigatedTo method. There you can access the journal and check the current entry. From there you should be able to determine if it came from View A or View B.
public void OnNavigatedTo(NavigationContext navigationContext)
{
var journal = navigationContext.NavigationService.Journal;
//use journal.CurrentEntry
}

How does an MVC system work?

I'm trying to learn the MVC pattern, but each place say something different. So now I don't know whats the true MVC.
So I'm guessing its the most pure MVC:
Model is just data and notify data changes.
View reads the messages of the Model to update the view.
Controller reads the user input from View and changes the Model according.
Implementing
Model knows no one.
View knows the Model.
Controller knows both View and Model.
Pseudocode:
/* Model */
class Color{
color = blue;
setColor(color);
notifyUpdate();
}
/* View */
class ColorPicker(model){
model.register(update);
update(){
this.colorToExhibit = model.color;
}
}
/* Controller */
class Colorize(view, model){
view.register(update);
update(color){
model.setColor(color);
}
}
Some questions:
Is that right?
I can't see why the View cannot change the Model directly, but through Controller.
Suppose I have animations to be performed after an action. Who must handle this animation: the Model, the View, or the Controller? Also: the animation logic is part of the Model, View, or Controller? More: Suppose a Poker game. After the user choose an action (say, 'Raise'), the system must play an animation (say, the chips going from player spot to the desk). How can I see this poker example (with animation) as a MVC? Can you explain and give a pseudocode about that?
Thank you.
Model is just data and notify data changes.
View reads the messages of the Model to update the view.
Controller reads the user input from View and changes the Model according.
The Model is more than just data. The model is also the business logic. It contains all of the intelligence of the system, or at least an abstraction of behind-the-scenes intelligence (such as database calls or other service calls). Consider the saying, "Keep your models heavy and your controllers light."
Model knows no one.
View knows the Model.
Controller knows both View and Model.
The Model knows no one, that it correct. The Model should be portable between applications and shouldn't depend on UI concerns in any way. (The View and the Controller are UI concerns in this case.)
The View knows the Model, also correct. The View basically "binds" to the Model. It presents all of the UI elements and places Model data within the UI elements accordingly.
The Controller kind of "knows the View." It knows which View to which it should direct control, but it doesn't know anything about that View. Nor does it know which View from which control previously came. The Controller responds to events. An event comes in from the UI, carrying some kind of state information with it (a ViewModel, perhaps), directs logical control through the Models (where the business logic happens), and responds with a Model (or a ViewModel, if the shape of the data specific to a particular View is different than the Models) and a View.
I can't see why the View cannot change the Model directly, but through Controller.
The View can manipulate the Model within the context of the user interaction, but shouldn't expect those changes to persist in any way. The View should be considered "client-side" and doesn't know anything "server-side." (Even if you're talking about a native application and not a web application.) Persisting any change is considered a UI "action" or "event" and would go to a Controller to make it happen.
Suppose I have animations to be performed after an action. Who must handle this animation: the Model, the View, or the Controller? Also: the animation logic is part of the Model, View, or Controller?
An animation sounds like an entirely UI-based operation. It would be within the View. Is there more happening than just a UI animation? Does the animation change anything in the back-end? For example, if I have a web application and, when a page loads, I want to fade-in some data (an animation)... that's entirely in the View. The data would be delivered to the View like any other data, and the animation takes place entirely within the UI (View). It doesn't do anything from the perspective of the Model or the Controller.
Suppose a Poker game. After the user choose an action (say, 'Raise'), the system must play an animation (say, the chips going from player spot to the desk). How can I see this poker example (with animation) as a MVC? Can you explain and give a pseudocode about that?
The action ("Raise") is a Controller event. The UI would contact the controller to perform the "raise". So the Controller might have a method like this:
View Raise(GameState state)
{
// Interact with the Models to update the known state of the game.
// The Models would perform the actual Poker game logic.
// Respond with a View bound to updated Models.
}
Once the Controller responds to the UI with a new View, that View would contain any animations to display to the user. (After all, you don't want to perform the animation unless the action was successful, right? When the Controller responds to the UI with a new View indicating a successful action, then the animation would play. It may instead respond to the UI with a View indicating an error, in which case that View would show something else.)
I'll go with the simple Bank analogy.
Tellers are Views.
Runners are Controllers.
Bankers are Models.
The Bankers are the smart ones, they know all of the business logic and do all of the complex calculations.
The Runners are used to transport the money (data) from the Bankers to the Tellers.
The Teller presents the money to the Customer.
A simple representation:
Model
public class BankAccount
{
public int ID;
public int Balance;
public BankAccount(int id)
{
ID = id;
Balance = DetermineAmount();
}
public int DetermineAmount()
{
// Gather transaction info, debits, credits and return a
// sum of the amount left in the account depending on the
// id provided.
}
}
Controller
public class BankAccountController
{
public ViewResult Index(int id)
{
BankAccount account = new BankAccount(id);
return View(account);
}
}
View
<ul id="account-info">
<li>Account ID: `#Model.ID`</li>
<li>Balance: `#Model.Balance`</li>
</ul>
If you are interested in the historical true MVC, then start with Trygve Reenskaug. He created (observed?, catalogued??) it in the late 1970s. For a start, read "Models-Views-Controllers" from 1979. It defines the terminology. Take careful note of it's title - all three roles are pluralized. This is the first thing that most people seem to get wrong.
The best description I've found of the original use of MVC is actually in a presentation dated 2004 entitled "Inside Smalltalk MVC". I would guess that the canonical papers that describe the Smalltalk 80 final version of MVC are Krasner & Pope's "A Cookbook for Using the Model-View-Controller User Interface Paradigm in the Smalltalk-80" and
Steve Burbeck's "Applications Programming in Smalltalk-80: How to use Model-View-Controller (MVC)". Both papers are well worth the read.
If you have some time to kill and don't mind listening to Robert Martin, he did a good keynote at Ruby Midwest 2011 that touched on MVC. It is a little over an hour, but quite entertaining and enlightening. I tend to follow with his opinion that most implementations get MVC wrong. I spent a little time looking around and finally found a diagram that I can link to which describes MVC. The one that I like came from Pope and Krasner.
(source: as3dp.com)
From my point of view, the following are the key points:
a model instance is responsible for notifying the interested objects of changes. Note that these can be any object instances. The diagram shows both views and controllers receiving updates here.
views are responsible for querying the current state and displaying the results. They usually perform filtering or data transformation as well.
controllers are responsible for accepting user input and forwarding view messages along to the view.
View messages are a common theme in MVC. It is important that these are independent of the UI world - these are not mouse clicks and what not but a view-specific language of events. This brings us to the next point.
The view does not depend on the controller in any way. Controller's are responsible for arranging and creating views and providing the interface between the rest of the world and the view.
In a perfect world, the view is responsible for making the model representation visible. This is how it worked when MVC was applied to desktop applications.
The reality is that MVC has been twisted and rewritten for the web world. It's not really MVC anymore or maybe MVC was simply redefined. This is why you are seeing so many different opinions and representations of MVC out there. If you are looking into writing desktop style applications, then look at the stuff by Krasner & Pope. If you are looking into how MVC is applied to the web, then I recommend Uncle Bob's keynote for an alternative that it better suited for web applications - what he called the Interactor, Entity, Boundary Architecture for lack of a better name. Dig around for stuff associated with his talks about "the Lost Years of Architecture".

ExtJS: Add Single Click Action To A Node In A TreePanel

[revised]
I'm creating a TreePanel in ExtJs that is loading its children from a JSON file. I'm having trouble adding a click action to the nodes. I'm not sure whether it's added in the script creating the tree, or if its added as a property in the JSON, and if so, what the syntax would be. Any help would be appreciated! Please provide an example if possible.
Add a listener to the TreePanel:
listeners: {
click: function(node, event){
console.log(node);
}
}
and use the data in the node.
This is a very commonly talked about question(events in general), so I would suggest searching the extjs forums and reading what they have in their learning center.
Event listeners can be assigned on creation of the TreePanel or attached to an existing TreePanel.
I have a similar (and common) setup where I have a tree that I use as a navigation menu and each leaf node acts as a link that should be opened in a TabPanel.
To handle the node clicks, you could do something like:
Ext.get('your-tree').on('click', function(node, event){
if(node.isLeaf()){
// do what you need to with the node.
}
});
Jozef Sakalos(aka Saki) has allot of great information on his site extjs.eu. I think you would be most interested in the component communication example.
Gerry is putting you on the right track, and you can never go wrong with Saki's examples. I just answered a very similar question. That answer may give you more information as well:
How do I find the selected node in an ExtJS TreePanel?

Resources