12 Mar 2012 11:19 AM #1
Unanswered: Why is there inconsistent use of HasSelectHandlers/HasClickHandlers?
Unanswered: Why is there inconsistent use of HasSelectHandlers/HasClickHandlers?
A strength of the update to version 3 is the usage of the GWT event system. This is somewhat undermined by the use of HasSelectHandlers in place of HasClickHandlers.
Buttons in the current release only implement HasSelectHandlers and this makes it difficult to pass widgets based on GWT interfaces. The use of HasSelectHandlers is not consistent though-out, there are a few button based widgets that actually do implement the GWT HasClickHandlers interface (IconButton, ToolButton, and SplitBar).
What advantage does implementing the HasSelectHandlers bring over HasClickHandlers?
13 Mar 2012 5:02 AM #2
I would add that I am annoyed that we have only SelectHandler in the tree (unless I missed something): it is called both when acting on the fold/unfold button (arrow or +/-) and when clicking on a node, while I would like to have two distinct events.
I think I mentioned it already somewhere on this forum... but it is relevant to this thread too.
Typical use case: in a file explorer, open (unfold) a full path in a tree without displaying the content of each and every folder in the path in the file list part.
Solved by using a Dom click handler on the node, but then we have only the node key, not the node itself with its metadata.
14 Mar 2012 6:35 PM #3
In short, click doesn't always cause a select, and a select doesn't always indicate a click.
There are cases where click makes sense (i.e. when you only want click events from the dom, not some other way that items possibly can be selected), and others were a more abstract look at the interaction makes sense. Buttons should be selectable by click, space, enter, and eventually touch events.
It is probably not necessary for IconButton, ToolButton to implement HasClickHandlers - HasSelectHandlers should be sufficient, and I'll make sure we review that before the final release. SplitBar makes slightly more sense - nothing is being selected, but moved.
Typically dom events are typically consumed internally, and logical events are exposed externally. As with most dom event, you can always add a click handler to a widget by using Widget.addDomHandler(myClickHandler, ClickEvent.getType()); - this method can be used for almost any event to be added to any widget.
Finally, looking at the Tree - this doesn't seem to implement HasSelectHandlers, but instead exposes a SelectionModel, which implements HasSelectionHandlers<T> - the difference is that SelectEvent is about the user interaction (click, enter, etc), whereas SelectionEvent<T> indicates that a piece of data has been selected. Tree.findNode allows you to pass in an element (for example as a result of a ClickEvent) and get the TreeNode<T> instance, which contains the metadata you are after. I'm not certain that selecting the +/- should cause a SelectionEvent, I'll file a bug to look into it.
15 Mar 2012 6:40 AM #4
I see your point, and it is valid. My issue comes when trying to implement MVP and being able to implement consistent interfaces.
The behaviour in the buttons I listed is nice for this type of pattern. When the onClick method is occuring, it is using this to throw a select event. The buttons implement the HasClickHandlers which allows for MVP to work. If I have multiple different views on the presenter, I need to start wrapping all the GXT widgets to get this behaviour. Not all views may implement HasSelectHandlers as it is a sencha specific interface.
15 Mar 2012 9:12 AM #5
One major concern with expecting HasClickHandlers is that this is specific to the dom event - this is the main reason we added our own, less dom-specific events for these cases. Buttons built out of html elements not typically designed to receive space or enter keystrokes as a click event will not send events out. GWT only provides a TextButton which wraps a <button> element - if they were to build a ImageButton or the like, either non-click events would need to be passed to added ClickHandlers, or another interface would need to be added, and then supported in your presenters.
If you are concerned with multiple view implementations, I would encourage you to look at the other MVP structure that the GWT documentation proposes, seen at this link: http://code.google.com/webtoolkit/do...AndPlaces.html . The basic idea is to let the Presenter expose methods that can be invoked from any view, whether simple or complex, touch or desktop.
The main idea is to describe the view/presenter relationship not as if the Presenter is just using a giant widget that exposes many events from different sources, but are two classes that interact. The main downside of this approach seems to be that view must be slightly smarter, handling widget events and turning them into presenter calls, offset by the fact that often there are two user-initiated ways of causing the same presenter method, and generally the presenter doesn't need to understand the difference. Plus, having only a presenter and a view interface makes testing much easier (no need to mock all of those Has*Handlers), and if you are using UiBinder, the @UiHandler methods can call directly to the exposed presenter methods.
15 Mar 2012 9:30 AM #6
Testability is the reason I am attempting to have my Presenter implement these types of interfaces. In the GWT link that you have included, the view contains a lot of specific logic. I am attempting to use the Passive View MVP (described here: http://martinfowler.com/eaaDev/PassiveScreen.html).
This level of abstraction allows for the view to be completely removed from unit testing, and testing all business logic that is driving the app to be automated. Test suites for the behaviour of your app do not require running application servers, browsers, etc. Platform tests, and integration tests can ensure that the application runs in a deployed environment, but they are less numerous since they are slower and often more brittle.
Additional benefits include being able to migrate to different widget libraries and upgrade to newer versions (assuming the interfaces don't change).
1 May 2012 8:23 AM #7
I have to agree with CPD, this is an annoying limitation. I came to upgrade my views to GXT3 (The production version) and immediately hit this problem: My View is dumb, it just lays out the Widgets and exposes them to the presenter via methods that return interfaces like HasClickHandlers and HasVisiblity. As CPD mentions, this means I don't have to unit test my view at all, I can leave it for integrations tests.
I am concerned with multiple view implementations, and applying this technique allows me too change the view; Take a look at the implementers of HasClickHandlers, all clickable widgets in GWT implement it, so I can switch out my Button for an Anchor, or TextArea or a Canvas etc etc.
As it stands I have 2 options: Change all the View interfaces to expose HasSelectHandlers or wrap the Sencha Widgets to implement interfaces, something I had to do with the previous version and was hoping I would not have to do in the new version.
2 May 2012 12:30 AM #8
- Join Date
- Aug 2010
- Germany, Solingen
- Vote Rating
Have you think about Reverse MVP?
2 May 2012 1:29 AM #9
I think Colin Alworth suggests something similar to Reverse MVP when he referenced the GWT article, confusingly there is another article (https://developers.google.com/web-to...p-architecture) that suggests using the HasXXXHandlers style.
I actually think both methods are valid, Reverse MVP allows you to completely hide all UI aspects but requires you to create a dependency between the view and presenter (albeit via an interface) the other means the view can be entirely dumb (No loops are conditions at all) and removes the need to test.
The original point of this post still holds: Why do the Sencha buttons not implement HasClickHandler? They are clearly clickable! I appreciate there are implementation reasons, but from a conceptual point of view it just seems wrong.
2 May 2012 5:14 AM #10
Keep in mind that even if we did implement HasClickHandlers, your code listening to those events wouldn't respond when users used tab and space/enter to select and activate your button. GXT buttons are not wrapping html elements that dispatch psuedo-click events when keystrokes are entered in order to have better cross browser consistency when sized or to respond to user interaction.
So even if we did, you would be skipping certain user events, unless you exposed them as HasClickHandlers and HasKey*Handlers and listened to them all. That is the point of the SelectEvent, to provide consistent widget logic, not just physical dom interaction.
With regard to GWT versus GXT widgets, I do agree that this is an inconsistency that is hard to deal with when building views that directly expose Has*Handlers as a way for the presenter to subscribe to interactions. That is why when I build GWT projects, with or without GXT, I use the other MVP style Google espouses, as outlined at https://developers.google.com/web-to...itiesAndPlaces, declaring an interface for the view and the presenter so that the presenter can outline what interactions it expects to be invoked from the view. In addition to this making presenters cleaner (no handlers) and less ui specific (no need to handle 'click' when you want to handle 'click and space and enter'), it is much easier to write unit tests - you invoke the presenter methods directly instead of mocking the view.