Given that you wish to add a "html page" to an existing GWT application, I suggest manipulating the DOM rather than creating a second entry point. What-if you need to create a contact page, about page, and privacy page for this application?
Chris's SO answer on GWT navigation gives a really nice solution for maintaing multiple states in a GWT application.
I have implemented my own variant based on Chris's answer; here, I only elaborate further with details of my implementation. I find this to be efficient for managing
several states in a GWT application with
history support.
As suggested, I use the following HTML:
<table id="wrapper">
<!-- Header row -->
<tr style="height: 60px;">
<td colspan="2" id="header"></td>
</tr>
<!-- Body row and left nav row -->
<tr style="vertical-align: top;">
<td id="leftnav"></td>
<td id="content"></td>
</tr>
</table>
I then defined a top-level Composite class, which each separate page inherits in the application:
public abstract class Content extends Composite{
public abstract String getToken();
public abstract String getWindowTitle();
}
The token and window title for each page are defined in a class called PageDefs:
public class PageDefs{
public static final String WelcomeToken = "WELCOME";
public static final String WelcomeTitle = "Welcome to My App";
public static final String AppToken = "APP";
public static final String AppTitle = "My App";
}
The Content class is used abstractly by the singleton ContentContainer:
public class ContentContainer implements ValueChangeHandler<String> {
@Override
public void onValueChange(ValueChangeEvent<String> event) {
String token = (String) event.getValue();
this.setContentByToken(token);
}
public void setContentByToken(String token) {
if (token.equals(PageDefs.WelcomeToken)) {
this.setContent(new WelcomePage());
} else if (token.equals(PageDefs.AppToken)) {
this.setContent(new MyApp());
} else {
Window.alert("Error in parsing history token: '" + token + "'");
}
}
private void setContent(Content content) {
RootPanel contentRoot = RootPanel.get("content");
contentRoot.clear();
this.content = content;
History.newItem(content.getToken(), false);
// check for special initializations:
if (content.getToken().equals(PageDefs.AppToken)) {
((MyApp) content).MyInit();
}
contentRoot.add(content);
header.setHeader(content.getWindowTitle());
Window.setTitle(content.getWindowTitle());
Window.scrollTo(0, 0);
}
private static ContentContainer myInstance = new ContentContainer();
public static synchronized ContentContainer getInstance() {
return myInstance;
}
private ContentContainer() {
History.addValueChangeHandler(this);
}
private Header header;
private Content content;
public void setHeader(Header h) {
this.header = h;
}
}
The ContentContainer keeps a local reference to the header class. This is because I needed a dynamic header and window title that depend on the state of the application. Further, everything from managing the content of the application, the header, the window title, and the history is all contained within one class.
In my actual implementation, the ContentContainer also keeps track of the user's session. Thus, the ContentContainer's onValueChange
method forces the log-in page to load if a user's session is absent or expired.
The header is a UI binder with one InlineHTML variable whose HTML is set by the setHeader
method. For the left navigational menu, I also use UI binder with GWT anchors with #WELCOME
and #APP
as the href values.
Finally, we need to load each section of the application in the entry point:
public void onModuleLoad() {
Header h = new Header();
h.setHeader(PageDefs.WelcomeTitle);
RootPanel.get("header").add(h);
ContentContainer.getInstance().setHeader(h);
RootPanel.get("leftnav").add(new NavMenu());
String token = Window.Location.getHash().length() == 0?
PageDefs.WelcomeToken : Window.Location.getHash();
ContentContainer.getInstance().setContentByToken(PageDefs.SignupToken);
}
That is how I manage multiple pages in my GWT applications. This extra work may seem arduous, but I find that it is worth the effort. If your application processes some input, and visualizes the output, forward and back buttons are intuitive navigational tools between the form and visualization.