can GWT Pages handle this?

23 views
Skip to first unread message

Joe Hudson

unread,
Aug 18, 2010, 5:09:12 PM8/18/10
to gwtpages-user
*email content copied to this forum

GWT Pages is actually the framework I am looking at most closely.
I've been doing GWT development for a while but so far I've steered
clear of MVP and all my history token management has been pretty
simple and done by hand. I'm still ambivalent about MVP but I'd love
to make my page architecture and history token processing more
elegant.

I have an app that is basically one TabLayoutPanel with several tabs,
and flipping between the tabs changes the history token. Initializing
the app with the history token should (obviously) open that tab.
There is an additional complication that some actions can open
additional tabs, and if the app initializes with the token for one of
those (generated) tabs, the app should start with one of them open.

Is GWT Pages designed to accomodate an application like this? It
seems like it but I'd love to be sure before I invest the time in
figuring it all out.

Thanks!

BTW feel free to move this to the GWT Pages discussion forum.

Joe Hudson

unread,
Aug 18, 2010, 5:24:21 PM8/18/10
to gwtpages-user
Yes, there are 2 different ways that parameters can be passed around
(as a list or as a map)... you can also pass around transient
parameters for a request that do not get serialized to the history
token by the way.

So, here is an example of what you have for your page:

public class MyPage implements Page {

@UiField
DecoratedTabPanel tabs;

public void onEnterPage(PageParameters parameters,
PageRequestSession session, AsyncPageCallback callback) {
// all of the parameters from the request can be retrieved
using the PageParameters object
// so here would be the code that you would put to load the
rest of your page

// say you defined the tab as the first parameter by index
int tabIndex = 0;
if (parameters.listSize() > 0)
tabIndex = parameters.asInteger(0); // this represents
the first parameter from the history token
tabs.selectTab(tabIndex);

// if you named your tabs, you could use the asString({param
index}) method to get the tab name
}

public void onSelection(SelectionEvent<Integer> event) {
String historyToken =
Pages.get().createHistoryToken("thisPageToken",
event.getSelectedItem());
History.newItem(historyToken, false);
}

... other methods in your class
}

then, you could use {app root}#thisPageToken/1 to view the first tab
or if you use tab names instead (which I would do) {app root}
#thisPageToken/details - you would just need to map that name to a tab
index

Does this make sense? And, is this what you are looking for?

Joe Hudson

unread,
Aug 18, 2010, 5:31:21 PM8/18/10
to gwtpages-user
I also wanted to mention 1 thing that you will probably run into when
building your app...

GWT Pages has a nice way of dealing with the asynchronous nature of
page loading...

By default, the page will be rendered as soon as the onPageEnter
method is executed but this might not be the best solution if you are
loading data asynchronously because you will see that annoying pop of
data when the async data request returns.

To handle this, all you have to do is use the AsyncPageCallback object
that is passed to the onPageEnter method -

simply call callback.waitForAsync() and then your page won't show up
until you call callback.onSuccess(). There are other method on the
callback for different situations like a failure or illegal access
which can be dealt with using the page event handlers.

Joe

Jeff Schnitzer

unread,
Aug 18, 2010, 5:51:57 PM8/18/10
to gwtpages-user
Hmmm, I don't think that does quite what I want. In my application,
each tab is effectively a page - this is the primary navigation
system. I want my URLs to look something vaguely like:

...app#profile
...app#matches
...app#who=blahblah

Note that there might be several #who=blah tabs; they open and close
on demand. The exact format of the token doesn't matter to me as long
as it makes sense to humans, so ...app#app/profile doesn't thrill me.

I have this working right now using a fair bit of custom code but I
feel like I'm reinventing something. I will go through the GWT Pages
code and see if I can adapt it to my model. If it makes sense I'll
try to contribute patches.

Thanks,
Jeff

Joe Hudson

unread,
Aug 19, 2010, 9:24:22 AM8/19/10
to gwtpages-user
Ok, I don't think I quite understood what you were wanting before...

if you have an application that is actually just a
single page, you can just use a custom page loader to provide a single
page regardless of the page token. Then you could use the page token
to evaluate for the tab identifier. GWT Marketplace is sort of doing
this... if you notice - the URL for your app is
http://www.gwtmarketplace.com/#objectify-appengine. This is because
if this page loader:
http://code.google.com/p/gwtmarketplace/source/browse/trunk/src/hudson/gwtmarketplace/client/PageLoader.java#46

Basically, you can just create a single page and always return that
page in the getPage method - I think this will do what you want. If
not, let me know.

Joe

Jeff Schnitzer

unread,
Aug 19, 2010, 6:52:58 PM8/19/10
to gwtpag...@googlegroups.com
I'm still combing through the code and the examples... but it's a
struggle for me. I think what I'm missing most is some sort of
conceptual documentation: What are the major players (Page,
PageLoaders, ApplicaitonPresenters, etc - there seem to be quite a
few), what do they do, and how do they interact? It would be great to
have it explained by way of a timeline of how a request is processed -
say, tracing the flow of when an app is loaded with a history token.

Regarding tabs vs pages:

If my app is a single page, does using GWT-Pages benefit me? Seems
like I'll just be back to managing all the tabs myself, but with a
bunch of extra framework on top that I'm not using.

Maybe I could use my tab panels as Pages and have my
ApplicationPresenter manage the TabLayoutPanel? I guess the problem
with this is that tabs switch when you click on them, but what I
really need to do is make it so when you click on a tab it changes the
URL #token, then the tabs get flipped appropriately through the normal
process. Maybe that's doable anyways, I'd just need to use a
BeforeSelectionHandler to stop the default behavior. Does that make
sense? I'm not even sure I'm asking the right questions yet.

Thanks,
Jeff

Joe Hudson

unread,
Aug 19, 2010, 8:58:01 PM8/19/10
to gwtpages-user
Yeah, sorry about that... I am working on the documentation right now
and should have more to go on in the next couple of weeks.

But, here is some high level info to get you going (if you are still
interested)

The major players are:
- The page: this is your presenter in MVP terms (the asWidget method
would return your view) or your your simple view page without MVP
where the asWidget would return *this*.
* A page is any class that implements
com.google.gwt.gwtpages.client.page.Page
* There are a few different types of base page classes (for
convienance only - not required) coming in the next release
> CompositePage: not for use with MVP but makes working with
UIBinder extremely easy
> PresenterPage: specifically for when using MVP pattern
> FlowPanelPage: not for use with MVP - extends FlowPanel

The application presenter: this is the component that takes pages and
renders them. This would contain your layout logic.
* An application presenter is any class that implements
com.google.gwt.gwtpages.client.page.ApplicationPresenter
* There are a few different types of base presenters to use - easy
to make your own though...
> CompositeApplicationPresenter: allows ability to register
multiple application presenters
> CompositeLayoutPresenter: allows ability to register
multiple application presenters that would involve switching using
RootLayoutPanel
> SimplePanelLayoutPresenter: very simple application
presenter which has not layout at all

The page loader: this is the class that is responsible for
instantiating pages and mapping a pages to page tokens (strings)
* A page loader is any class that implements:
com.google.gwt.gwtpages.client.page.loader.PageLoader
* There are a few different page loaders to deal with different
ways of loading pages
> StandardPageLoader: creates pages synchronously using
GWT.get(...);
> AsynchPageLoader: creates pages asynchronously using
GWT.gwt(...) but does this inside a GWT.runAsync
> StandardGinPageLoader: creates pages synchronously using
GWT.get(...); - automatic Gin injection... this is in the Gin add-on
> AsynchGinPageLoader: creates pages asynchronously using
GWT.gwt(...) but does this inside a GWT.runAsync - automatic Gin
injection... this is in the Gin add-on
* with the previous page loaders, there a few different ways to
register classes and your MVP presenter and page coupling is done
here. There are few different ways presenters can have views set
- single constructor parameter
- setDisplay method
- setView method


The next one is used but is not as important as, in most cases, would
not need to be modified:
The page tokenizer: this is responsible for getting data from the
history token and creating a history token from a page token and data
combination
* A page tokenizer is any class that implements:
com.google.gwt.gwtpages.client.page.parameters.Tokenizer

Joe
> >http://code.google.com/p/gwtmarketplace/source/browse/trunk/src/hudso...

Joe Hudson

unread,
Aug 19, 2010, 8:59:22 PM8/19/10
to gwtpages-user
Oh, and you are right... although I think GWT Pages is a fairly
lightweight framework, it may be overkill for what you are trying to
do.

Joe
> >http://code.google.com/p/gwtmarketplace/source/browse/trunk/src/hudso...
Reply all
Reply to author
Forward
0 new messages