gwt generic page level click handler - gwt

I have this situation, where I display a success/error message on a page and then I want it to disappear when the user does anything on the page (I assume that that triggers a click event, I can ignore events like going to new tab/windows etc.).
I have other "uihandlers" and "clickhandlers" on the page. So if I click empty regions on the page only the hidemessage call fires, else if I click valid 'clickable' elements my hidemessage fires first followed by the relevant handler.
Is there a way I can achieve this without adding hidemessage to all my clickhandlers on the page?
Edit: The message widget is not a PopupPanel, so setAutohide(true) won't work. But it is exactly the behavior I'm looking for. The widget is a custom widget which extends Composite implements HasWidget, HasClickHandlers

You can do this on your error message:
myPopupPanel.setAutoHideEnabled(true);
It does exactly whet you need. You may also consider setting auto-hide on history events (mostly back button):
myPopupPanel.setAutoHideOnHistoryEventsEnabled(true);
EDIT:
If you are not using a PopupPanel, you can make your Widget implement EventPreview, and then:
public boolean onEventPreview(Event event) {
Element target = DOM.eventGetTarget(event);
boolean widgetIsTarget = (target != null) && DOM.isOrHasChild(getElement(), target);
setVisible(widgetIsTarget):

Related

GWT - How to handle multiple handlers for the same event

I'm currently working on a GWT project. I have a common block shared between multiple pages. I have some action buttons on that common block and the pages have a handler for the event launched on the click of those action buttons.
The problem I'm facing is that when I click on one of those action buttons on Page A, the handler from Page B previsouly registered would be called too.
So the solution I thought of was to remove the handler from a page when we leave it so there would be only one page at once with a registered handler to the same action button event.
First, I register to the action button click events and save the HandlerRegistration object returned from the addHandler method:
HandlerRegistration actionButtonClickEventHandlerRegistration=eventBus.addHandler(CommonBlockActionButtonClickedEvent.TYPE, someHandler);
And then, on page change event, I call removeHandler from the previously saved HandlerRegistration object
eventBus.addHandler(PageChangeEvent.TYPE, new PageChangeEventHandler() {
#Override
public void onMainPageChange(PageChangeEvent event) {
actionButtonClickEventHandlerRegistration.removeHandler();
}
});
So I do that on every pages, except that when I lauch my app and go to two of those pages, I get this error:
Caused by: java.lang.AssertionError: redundant remove call
Do you guys have any idea of why I'm getting this error or another way to solve my issue ?
Thanks a lot !
I would set the handler to null after removing it and I would check if it is actually null before removing it.
Like this:
eventBus.addHandler(PageChangeEvent.TYPE, new PageChangeEventHandler() {
#Override
public void onMainPageChange(PageChangeEvent event) {
if(actionButtonClickEventHandlerRegistration != null ) {
actionButtonClickEventHandlerRegistration.removeHandler();
actionButtonClickEventHandlerRegistration = null;
}
}
});
Nevertheless you seem to remove the handler at least twice and should check your program logic for that.
A good approach to do that is to set a breakpoint in the debugger (of your browser) on the line removing the handler. If you look at the call stack for every call to it, you should be able to spot the duplicate call and fix it.

Set focus to an Input in a gwtbootstrap3 Modal

I want to set the focus to a certain field (org.gwtbootstrap3.client.ui.Input) in a dialog (org.gwtbootstrap3.client.ui.Modal) before the dialog shows up. The use case seem quite common, if you have a dialog with a single field like the Upload text or Add feed dialogs right here. However I could not figure out how to set the focus to this particular gwtbootstrap3 component.
The Input component does have a setFocus(true) method. I assumed that setting the focus before showing the dialog would not work, which it doesn't. So the logical solution is to put the method call inside a ScheduledCommand. Like this:
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
#Override
public void execute() {
textField.setFocus(true);
}
});
That usually works with GWT standard components, but does not seem to help in this case. I found a way to get notified once the dialog is shown through a ModalShowHandler. Like this:
modal.addShowHandler(new ModalShowHandler() {
#Override
public void onShow(ModalShowEvent evt) {
textField.setFocus(true);
}
});
I even tried to combine both, adding a deferred call to the handle. No luck. Any ideas?
You should be listening on the ModalShownEvent (note: Shown, not Show).
ModalShowEvent is fired when the modal is requested (for example, programmatically) to be shown.
ModalShownEvent is fired when the modal is actually shown.
This somewhat confusing naming is based on the events of the native Bootstrap Modal's events: show.bs.modal and shown.bs.modal.
ModalShownEvent combined with the usual Scheduler#scheduleDeferred should do the trick.

Is there a way to tell when a Widget is shown with GWT?

I'd like to respond to an even whenever my widget is made visible on a page done with GWT and UI Binder.
Is there anything similar to the onAttach() event handler (which fires when the widget is added to the DOM), pertaining to when the widget is actually made visible?
I'd like to be able to handle the even when the widget is shown because there are a few different ways of making it visible, and I'd like a single place on the widget itself that can handle this event.
Thanks
I know this is an old question, I have faced the same problem before. What I did was override the setVisible(boolean visible) method in the widget, then perform whatever I needed to do:
#Override
public void setVisible(boolean isVisible) {
super.setVisible(isVisible);
if(isVisible) {
// Do whatever you need to do with your widget
}
}
The widget should be visible once added to the DOM unless you've intentionally hidden it (i.e. with CSS or hid it behind another widget). Normally, onAttached() means its on the page. If you're using CSS classes to make it visible, write a setVisible(boolean isVisible) method to your widget and set the visibility class this way. If you have it behind another widget (i.e. in layers) then you'll need to write your only logic to determine when it's visible.
There is no browser event for this, but you could try this:
With your widget you could check the elements getLeftOffset (or similar method), if you get a positive value, you could fire your method, and set a flag to indicate that your onVisible() method had fired.
Then once the getLeftOffset returns a 0 you could reset your flag, ready to fire your event again.

Best Practices GWT Event Handling

I have a question regarding the event handling on client side in GWT.
In our application we have a quite complex structure of different modules and pages which are communicating via the gwt eventbus on client side. Now the amount of events is growing to fast for my opinion. E.g. I am opening a popup I need:
An event for opening the popup
An event for asking some data within the client
An event for getting back the data and fill in the dialog
An event for closing the popup
An event for handling the save Button
Am I thinking a little bit to complicated or missing something in the EventBus implementation? I just wanted to have some feedback out of the community as you are facing the same issues.
For what it's worth, I have lots of events and more growing. And yes, I wonder if I can do with less, but when I skip an event and link elements directly, I regret it.
Here's an example that I just fixed up yesterday. I have a DataGrid widget. I also support re-ordering of columns, hiding of columns, re-sizing columns, and coloring columns with a popup dialog. You click on a configure button, and a popup with the columns listed shows, and the user can click checkboxes to show or hide columns, click on a Move Up / Move Down button to re-order columns, and so on. Hit Apply on the popup and the popup disappears and the DataGrid re-configures.
Except that it didn't. You'd click on Apply and the popup would just sit there, the user would wonder what was going on, the DataGrid would re-configure underneath, and then the popup would go away. We're only talking a short amount of time -- maybe a second or a bit more -- but it was so so noticeable. Why was it happening? Because I got lazy and tied the popup directly to the configure button, and the Apply button directly to the DataGrid. You'd hit Apply, for example, and the call would be made to the DataGrid with the new configuration information. Only when the call returned would the popup would be torn down.
I knew it was bad when I did it, but I was being lazy. So I took the 20 minutes I needed to write up two messages and associated handlers in my mediator singleton. One message is issued by the DataGrid to start the configuration dialog, and one is issued by the popup to configure the DataGrid. Now the widgets are de-coupled, and the performance is much snappier. There is no sense of "stickiness".
Now to your example, can you not combine (1) and (2)? And also (3), (4), and (5)? When the user clicks the configure button on my app, the event carries with it the current configuration information (including a reference to the DataGrid that originated the request). You can call this information the "payload". When the user clicks the Apply button on the popup, the event payload includes all the new configuration information (including a reference to that original target DataGrid) that the event handler feeds to the target DataGrid when the event is handled. Two events -- one to kick off the configuration and one to apply the end result.
Yes there are a plethora of events in any app that does something interesting, but events can carry a lot of information, so I would look at whether your event organization is too fractured.
As a extra bit, here is the code I use. I shamelessly copied elements of this pattern from one of Google's examples.
The user can ask for help using a menu item:
#UiField
MenuItem help;
help.setCommand(new Command() {
#Override
public void execute() {
BagOfState.getInstance().getCommonEventBus().fireEvent(new MenuHelpEvent());
}
});
For the event (in this case, the event fired when the user clicks on the Help menu item):
public class MenuHelpEvent extends GwtEvent<MenuHelpEvent.Handler> {
private static final Type<Handler> TYPE = new Type<Handler>();
public interface Handler extends EventHandler {
void doMenuHelp();
}
#Override
public GwtEvent.Type<Handler> getAssociatedType() {
return TYPE;
}
#Override
protected void dispatch(Handler handler) {
handler.doMenuHelp();
}
public static HandlerRegistration register(EventBus eventBus, Handler handler) {
return eventBus.addHandler(TYPE, handler);
}
}
I have a singleton called Mediator in which ALL events are registered:
MenuHelpEvent.register(BagOfState.getInstance().getCommonEventBus(),
new MenuHelpEvent.Handler() {
#Override
public void doMenuHelp() {
new MenuHelp().execute();
}
});
Every event is mated with a Command object to do the work:
public class MenuHelp implements Command {
#Override
public void execute() {
new InfoMessage(BagOfState.APP_MSG.unimplementedFeatureCaption())
.setTextAndCenter(BagOfState.APP_MSG.unimplementedFeature());
}
}
Everything is decoupled. The menu widget is bound to a command that executes and then completes. The command fires the event on the bus then completes. The event fires off the execution of a Command and the completes. The Command shows the popup help panel (in this case, an "unimplemented" message to the user -- yeah, I'll get to it soon). Every interaction with a user's input is handled extremely quickly and resolves. It can kick off a series of events to perform a long action, but never tying up the GUI to do so. And of course, since the elements are decoupled, I can call the same elements in other places (for instance, call the help Command through a button push as well as a menu item).

Disable user interaction in a GWT container?

I want to disable/enable user interaction (mouse click more specificly) on many widgets like hyperlink, button, etc which are contained in a composite (flextable)
there are more than one click handlers, and I don't want to bother with removing and adding listeners according to mode (interaction enabled/disabled)
Any ideas would be appriciated...
You forgot to mention the version of GWT. In GWT 2.0 you can use this code snippet or something similar. This feature allows you to cancel events before they are handed over to the target widget.
Event.addNativePreviewHandler(new Event.NativePreviewHandler() {
public void onPreviewNativeEvent(NativePreviewEvent pEvent) {
final Element target = pEvent.getNativeEvent().getEventTarget().cast();
// block all events targetted at the children of the composite.
if (DOM.isOrHasChild(getElement(), target)) {
pEvent.cancel();
}
}
});
There is a GlassPanel compoent in google-web-toolkit-incubator. I am almost sure it does what you need. Either way, it is a good idea to cover a disabled component whit one of these.