How to show a “Loading…” pop-up in your GWT app
Posted by David Chandler on October 22, 2009
Last week, I posted a technique for displaying a splash screen before GWT loads. In this post, we’ll look at a way to show a modal pop-up after your app is up and running, but while GWT is making AJAX calls.
The basic idea is to show and center a pop-up with some text and an Ajax wait image. There are a couple ways to hook it into gwt-presenter. The WidgetDisplay interface method has startProcessing() and stopProcessing() methods that get called by the DisplayCallback class that you pass to dispatch.execute(). If you want to show the pop-up for only one presenter, then you can simply implement these methods in your view. More likely, however, a centered pop-up will be used by multiple presenters, in which case we can create an AppLoadingPresenter and AppLoadingView that will listen for an AppLoadingEvent. Any presenter or service can then fire the AppLoadingEvent to cause the “Loading…” panel to be shown. Here’s some very elegant code courtesy of my co-worker Tony Richardson. I’ll leave it up to you to create the AppLoadingEvent and fire where you need it. One more note: I’m reusing the AppLoadingEvent to trigger both showing and hiding the pop-up by means of a boolean argument in the AppLoadingEvent constructor. It might be more correct to use separate events for this, but it’s getting late…
package com.roa.client.presenter; import java.util.List; import net.customware.gwt.presenter.client.EventBus; import net.customware.gwt.presenter.client.place.Place; import net.customware.gwt.presenter.client.widget.WidgetDisplay; import net.customware.gwt.presenter.client.widget.WidgetPresenter; import com.google.inject.Inject; import com.roa.client.event.AppLoadingEvent; import com.roa.client.handler.AppLoadingEventHandler; public final class AppLoadingPresenter extends WidgetPresenter<AppLoadingPresenter.Display> { public interface Display extends WidgetDisplay { void showWidget(); } private final Display display; private final EventBus eventBus; @Inject public AppLoadingPresenter(Display display, EventBus eventBus) { super(display, eventBus); this.display = display; this.eventBus = eventBus; bind(); } @Override public Place getPlace() { // We won't really use this presenter as a Place return null; } public void hideLoading() { this.display.startProcessing(); } @Override protected void onBind() { registerHandler(this.eventBus.addHandler(AppLoadingEvent.TYPE, new AppLoadingEventHandler() { @Override public void onAppLoadingEvent(boolean isComplete) { if (isComplete) { display.stopProcessing(); } else { display.startProcessing(); } } })); } @Override public void revealDisplay() { display.showWidget(); } }
And here’s the AppLoadingView. Very simple, but cool effect.
package com.roa.client.ui.web; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.HasText; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.Widget; import com.google.inject.Inject; import com.roa.client.presenter.AppLoadingPresenter.Display; public final class AppLoadingView extends PopupPanel implements Display { private final FlowPanel container = new FlowPanel(); public AppLoadingView() { final Image ajaxImage = new Image("path_to_ajax_wait_image"); final Grid grid = new Grid(1, 2); grid.setWidget(0, 0, ajaxImage); grid.setText(0, 1, "Loading..."); this.container.add(grid); add(this.container); } @Override public Widget asWidget() { return this; } @Override public void stopProcessing() { hide(); } @Override public void startProcessing() { center(); show(); } @Override public void showWidget() { startProcessing(); } }
Subhro said
Your post helped a lot. Though I am not using gwt-presenter, i am implementing MVP as given in the article “Building large scale application in GWT” in the google docs for GWT.(home grown solution!!).
Thanks again.
Subhro.
Steff said
Is there a small example how to use this snippet?
Create EventBus, fire event, etc?
Thanks
Keywords said
Rank…
[…]How to show a “Loading…” pop-up in your GWT app « TurboManage[…]…
sonam said
Hey David,
I am using your code but when i have an operation like ‘loading a table ‘ the screen frizzes essentially the loading image too.It kinda ruins the whole purpose .Any clues?
David Chandler said
When the browser is really busy loading JS or rendering, there’s not much that can be done to prevent freezing. In general, the fewer things you try to do at once, the better, so you could try GWT code splitting or loading a smaller set of data initially.
sonam said
Thanks:)
Will look into offloading or loading things gracefully