TurboManage

David Chandler's Journal of Java Web and Mobile Development

  • David M. Chandler


    Web app developer since 1994 and former Developer Advocate with Google now residing in Colorado. Besides tech, I enjoy landscape photography and share my work at ColoradoPhoto.gallery.

  • Subscribe

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 241 other followers

  • Sleepless Nights…

    October 2009
    S M T W T F S
    « Sep   Nov »
     123
    45678910
    11121314151617
    18192021222324
    25262728293031
  • Blog Stats

    • 876,139 hits

I *like* code like this: easiest possible navigation with gwt-presenter

Posted by David Chandler on October 1, 2009

Here’s a super easy way to trigger a view transition and pass a parameter using gwt-presenter:

...
import net.customware.gwt.presenter.client.place.PlaceRequest;
...
		PlaceRequest placeRequest = new PlaceRequest(ManageListsPresenter.PLACE)
			.with(ManageListsPresenter.PARAM_TEST, "34")
			.with(ManageListsPresenter.PARAM_ANOTHER, "hello");
		Hyperlink my_lists = new Hyperlink("My Lists", placeRequest.toString());

That’s it! No ClickHandlers needed, and gwt-presenter takes care of all the rest.

The PlaceRequest.with() method is a nice touch to gwt-presenter. It all ends up on the URL, which is important for GWT’s History mechanism, and it’s a clean way to generate the URL. Of course, there are corresponding getParameter methods to extract passed parameters from a PlaceRequest, which you would typically do in the presenter’s onPlaceRequest() method.

So what happens when the user clicks the link? The view associated with the requested presenter is shown, the place is marked in GWT’s History mechanism, and the presenter’s onPlaceRequest() method is invoked. No ClickHandlers on the Hyperlink are required to make this happen. When the user clicks a Hyperlink, GWT fires a ValueChangedEvent on History, which is picked up by gwt-presenter and sets off the chain reaction. Even if the requested presenter belongs to a container (WidgetContainerPresenter) that is not currently shown, gwt-presenter calls revealDisplay() on the presenter and its container if needed to bring it to the front.

If you want to use a Button, Label, etc., instead of Hyperlink, you can simply add a ClickHandler and fire the same PlaceRequestEvent that gwt-presenter uses under the covers in response to a Hyperlink:

		display.getAddButton().addClickHandler(new ClickHandler()
		{
			@Override
			public void onClick(ClickEvent event)
			{
				PlaceRequest placeRequest = new PlaceRequest(AddPrayerListPresenter.PLACE);
				eventBus.fireEvent(new PlaceRequestEvent(placeRequest));
			}
		});

Note: the browser only updates the URL in the address bar in response to a Hyperlink. If you use a Button or other ClickHandler and want to update History and the URL in the address bar, you must also fire a PlaceChangedEvent(), typically in the onPlaceRequest() method that gets called by the original PlaceRequestEvent(). This results in a call to GWT’s History.newItem().

	@Override
	protected void onPlaceRequest(PlaceRequest request)
	{
		// necessary when we've fired PRE from code vs Hyperlink
		eventBus.fireEvent(new PlaceChangedEvent(request));
	}

Long-time Web developers will of course recognize that the basic Hyperlink as created above is the same as we’ve been doing for 15 years now. The beauty of gwt-presenter is that with the same simple URL construction, you can easily target one section of the page for dynamic update, and do it in a way that works with browser history and bookmarks to boot. There might be something to this GWT thing.

Advertisements

11 Responses to “I *like* code like this: easiest possible navigation with gwt-presenter”

  1. […] also a previous post on this […]

  2. Andy Stevko said

    Hi David,
    Great blog – you really saved me a lot of bleeding.

    One addition to this post that would be valuable is how to retrieve the parameters within the Presenter.

    While tracing the event path, I figured the place is either in revealDisplay() or onPlaceRequest(). Unfortunately I’m getting multiple calls to both (for a single click on an anchor) sometime with, sometime without the parameters.

    @Override
    protected void onPlaceRequest(PlaceRequest request) {
    // parse out the parameters
    String myVar1 = request.getParameter(“MyVar1”, “” );
    String myVar2 = request.getParameter(“MyVar2”, “”);
    /* … place state initialization code here …*/
    super.onPlaceRequest(request);
    }

    Do you have any better ideas for where to retrieve the parameters?
    –Andy

    • Thanks, Andy. onPlaceRequest() is definitely the correct place to retrieve parameters. Since you mentioned a Hyperlink and duplicate requests, you might check for a stray ClickHandler on the Hyperlink. There’s no need for it with gwt-presenter if you construct the link as shown in this post.

  3. Anh-Tuan said

    Hi David,

    Great blog with great posts!

    Places are a good way to manage simple history & navigation, but could you give us an example when a page is composed of several container with multiple views? More precisely let say I want to enable bookmarking of a page with ManagePrayerList in one container and AddChurchList in another, how could you do this, with composite places names, parameters or something else?


    Anh-Tuan

    • I’ve wrestled with this myself. In previous systems where I’ve had to so something similar, I used URL parameters, which would work nicely with gwt-presenter as each presenter’s onPlaceRequest method could pull out the params it cares about and perhaps fire PlaceChangedEvents based on them. But in my current project, I’ve opted to eliminate use of nested containers so I don’t have to deal with this…

  4. Janaki said

    Hi David,

    Thanks very much for this blog. It provided lot of insightful information on using GWT-MVP.

    I have a question on view transition from one GWT module to another. As per my understanding, in this blog, you have discussed about the view transition within a GWT module.

    For view transition from one GWT module to another – I was planning to send some data as query parameters to the new module and in it’s onModuleLoad, grab those query parameters , do the required processing and then fire the relevant PlaceRequestEvent whose corresponding Presenter’s revealDisplay() is going to show the view.

    Does all this make sense?

    I have one question in general – What is your advice on modularizing the GWT application? For e.g if we have half a dozen tabs in the application, should we create GWT module/application for each tab or should we have one top level module encompassing module for each of the tab.

    I guess the advantage of having one top level module would be that the view transition becomes much simpler (something similar to what you wrote in this blog). However, on flip side, the GWT module/application will become fat since all modules will be GWT compiled into a single application.

    Thanks in advance,

    Janaki

    • Thanks, Janaki. One module is definitely the easiest to work with, though it can grow large, as you suggest (which noticeably slows down compilation). I haven’t worked much with code splitting and runAsync in GWT 2, but I know those features are designed to improve modularity. I would keep it simple and break into modules only when performance requires it.

  5. Jon said

    How do you get it to load based on the url? In my app presenter, i have a if/else for logged in. If they’re logged in, I formerly had a fire current place method. Now what do I do?

    a placerequest event? what do I pass it?

    thanks!

  6. Is this what you’re looking for?

    String currentPlace = History.getToken();
    if (“”.equals(currentPlace))
    {
    // Load default view
    eventBus.fireEvent(new PlaceRequestEvent(new PlaceRequest(DefaultPresenter.PLACE)));
    }
    else
    {
    // Load requested page
    placeManager.fireCurrentPlace();
    }

    • Jon said

      placeManager.fireCurrentPlace(); is what I had in there, but it didn’t seem to be working. I’m using the new branch of gwt-presenter that uses Places. Dunno if that code is the same for that branch. Any experience with the new stuff?

      Thanks, David!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: