Joshua Java

Using GWT’s Hyperlink widget

Posted on: October 24, 2008

Okay, so here’s the problem what I faced recently. I’m doing a research on using GWT because we’re currently evaluating whether or not to use GWT in the future. I am trying to use GWT and stuck on using the Hyperlink widget. There were two problems that I faced:

  1. First I need to figure out how does Hyperlink changed the content of our view. Well in traditional web framework, you just fire out the page file with the href attribute. This is not the case with GWT. Because everything is done in Asynchronous way. Gee weez I always had problem thinking in Asynchronous way of thinking.
  2. Okay, when I have solved that, I came into the next problem. When user clicked the link and user hit the back button it should redirect me to the previous content. Remember when I said that with GWT you don’t actually fire out the file name?
     

Now you must be saying: “Yeach mate, there’s already an example in the GWT’s Showcase example complete with the source code.” Okay you’re right, but the problem is, the code is too complex, there’s already custom code in it which makes it really difficult to understand the niche of GWT itself. “But mate, there are already numerous blog entry that wrote about this”. Well all of them only writes on how to display the historyToken, but this is not what we’ll do in real application.

Okay to get this started with, install and create your GWT project as you may have know of. And now we shall go on to the meat and I’ll try to make this as simple as possible since I have to learn it the hard way.🙂

Now open up your entry point class which is located under the client package (or folder) of your just created project, and write this down on the onModule method:

    public void onModuleLoad() {
        MainPanel panel = new MainPanel();
        RootPanel.get("wrap").add(panel);
        panel.setWidth("100%");
        panel.setHeight("100%");
        panel.init();
    }

Okay, the MainPanel is the Panel that we’ll create in a very few short moment. The RootPanel is GWT’s panel where all of the other widget is filled in. We will insert the MainPanel to the RootPanel. Now you may have seen the wrap parameter in RootPanel.get method, and wondering what is that parameter ‘wrap’ is all about. Well that is the html element id which we will see in a very few short moment. So the idea is, RootPanel will get that element id to be populated with the MainPanel widget.

Now open up html file which is located under the public folder and add this inside the body element:

<div id="wrap">
   <div id="left"></div>
   <div id="right"></div>
   <div class="clear"></div>
</div>

Now you can see the wrapper, which will wrap the entire layout in the application and where the MainPanel widget will be populated. Now since div has a block behaviour which means that each div will go under the previous div, we need to decorate it with css so that the right div will go beside the left div. Now open up your css file located under the same folder as the html file and add this lines:

#wrap{
    width:100%;
}

#left{
    float:left;
    width:25%;
}

#right{
    float:left;
    width:70%;
}

.clear{
    clear:both;
}

Okay that will do for now. Now that we’re done with the layout business, it’s time to mess around with the Java side. Now let’s create the MainPanel which extends GWT’s Composite and implements the HistoryListener:

public class MainPanel extends Composite implements HistoryListener {
}

And now let’s add some fields into it:

    public static final String INIT_STATE = "initstate";

    FlowPanel panel;
    VerticalPanel left;
    VerticalPanel right;
    Label label;

    Map<String, Widget> cache = new HashMap<String, Widget>();
  • Okay the INIT_STATE is just a flag saying that nothing has been clicked yet and we’ve just entered the page.
  • The next block is the panels that we will populate with the Content widget and the Hyperlink widget. Content widget is the widget that we will create by ourself.
  • And the last is the cache where we will store all the recently clicked widget to be retrieved later when user hit the back or forward button.
  • Now we need to add something to the constructor as such:

        public MainPanel() {
            panel = new FlowPanel();
            initWidget(panel);
    
            left = new VerticalPanel();
            RootPanel.get("left").add(left);
    
            right = new VerticalPanel();
            RootPanel.get("right").add(right);
        }
    

    The panel will act as a dummy panel here, because I’d prefer filling in the Widgets to the RootPanel instead because it is easier for the web designer to setup the page for us to use (that is if you’re working in multiple team members with many different roles). After that don’t forget to init this Widget to be wrapped by the composite. Next is the panels where the links and the content will be located. In this example the left panel will be used for the menus and the right panel will be used for the contents.

    Now we need to define what happens when the historyChanged and initialize the History by adding two methods as such:

        public void init(){
            History.addHistoryListener(this);
            String token = History.getToken();
    
            if (token.length() == 0) {
                onHistoryChanged(INIT_STATE);
            } else {
                onHistoryChanged(token);
            }
        }
    
        public void onHistoryChanged(String historyToken) {
           if (historyToken.equals(INIT_STATE)) {
                label.setText("There is no token passed in the browser URL");
            } else {
                label.setText("Got a new browser history change token:" + historyToken);
    
                Widget widget = cache.get(historyToken);
                right.clear();
                right.add(widget);
           }
        }
    

    The init method is where we initialize the History and onHistoryChanged is what happens when the browser’s history has changed, this is the method that we must implement as the HistoryListener’s class. The meat is when the historyToken is not in initial state, then we will retrieve the widget that is added in the cache and populate it back to the panel. But when did we add the Widget to the cache? Okay here it is:

        @Override
        public void onLoad() {
            
            final Hyperlink link1 = new Hyperlink("Content One", "ContentOne");
            final Hyperlink link2 = new Hyperlink("Content Two", "ContentTwo");
            label = new Label();
    
            left.add(link1);
            left.add(link2);
    
            right.add(label);
    
            final ContentOne one = new ContentOne();
            final ContentTwo two = new ContentTwo();
    
            link1.addClickListener(new ClickListener() {
                public void onClick(Widget sender) {
                   right.clear();
                   right.add(one);
                   cache.put(link1.getTargetHistoryToken(), one);
                }
            });
    
            link2.addClickListener(new ClickListener() {
                public void onClick(Widget sender) {
                   right.clear();
                   right.add(two);
                   cache.put(link2.getTargetHistoryToken(), two);
                }
            });
        }
    

    The onLoad method defines what happens when this MainPanel widget is loaded and it is overridden from the Composite class. Here we add our Content to the right panel and the links to the left panel. Here we also defines what will happen when user click the links. In the click listener method is where we add the widget to the cache and populate it to the panel.

    Now the last thing we need to add is the Content widget which is as such:

    public class ContentOne extends Composite {
        public ContentOne() {
            VerticalPanel panel = new VerticalPanel();
            initWidget(panel);
    
            Label label = new Label("This is ContentOne");
            panel.add(label);
        }
    }
    

    Now you just copy for the rest of the Widget you want to add.

    There you go. Now that we understand the basic usage of Hyperlink, we can start working on something more complex in a real application. Feel free to comment on this.

    References:

    1. GWT’s Hyperlink Javadoc 
    2. Managing History and Hyperlinks

5 Responses to "Using GWT’s Hyperlink widget"

Hi

I tried the example but when clicked the Refresh button after history token changed to “ContentOne”,getting the error-“Failed to load the module”

Can you please tell what can be the reason?

You have to create ContentOne, it’s a widget.

Hello buddy! I’m having a exception when I press the Forward button of the browser! Do you know something about it?

Good example! To fix exception changethe function onHistoryChanged like this:
public void onHistoryChanged(String historyToken) {
….
if(widget != null)
{
right.clear();
right.add(widget);
}
….
}

Joshua, the future talking here. Sounds like you better do a CS degree. You need a solid founding in concepts old mate.

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: