Appirio's Tech Blog

Wednesday, January 20, 2010

Google Web Toolkit UiBinder Tutorial

Jeff Douglas

I’ve been working on a new project the past couple of weeks that (fortunately) requires Google Web Toolkit (GWT) and I wanted to use the new UiBinder that was released with GWT 2.0 in early December for a number of reasons (clean separation of UI and code, easier collaboration with designers, easier testing, etc ). However, I was having a hard time getting my head wrapped around it given that the GWT site has very little documentation and only a few examples. I’ve combed through the message boards, the docs and the sample Mail application that comes with the SDK and after finally groking the new functionality, I put together a little Hello World app, the kind that would have helped me out originally.

So I’m making some assumptions that you already have the GWT SDK and Eclipse Plugin installed and are familiar with both of them. If you are not, take a look at the GWT site for more info.

To get started, create a new Web Application Project called “HelloUiBinder” in the package of your choice but do not check “Use Google App Engine”.



Now create a new UiBinder template and owner class (File -> New -> UiBinder). Choose the client package for the project and then name it MyBinderWidget. Leave all of the other defaults. When you click Finish the plugin will create a new UiBinder template and owner class.



Open the MyBinderWidget.ui.xml template and add the following code. With GWT you can define your styles either in your template where you need them or externally. I’ve added a small style inline that adds some pizzaz to the label. Notice the field name myPanelContent in the template. You can programmatically read and write to this field from the template’s owner class. So when the owner class runs, it construct a new VerticalPanel, does something with it (probably add some type of content) and then fill this field with it.

Attributes for the elements (the text attribute in the Label element for example) correspond to a setter method for the widget. Unfortunately there is no code completion to get a list of these attributes in Eclipse when you hit the space bar so you either have to know the setters or refer to the JavaDocs each time. A painful process.





.bolder { font-weight:bold; }








For the owner class, MyBinderWidget.java, add the following code. In this class, a field with the same name, myPanelContent, is marked with the @UiField annotation. When uiBinder.createAndBindUi(this) is run, the content is created for the VerticalPanel and the template field is filled with the new instance.


package com.jeffdouglas.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class MyBinderWidget extends Composite {

private static MyBinderWidgetUiBinder uiBinder = GWT
.create(MyBinderWidgetUiBinder.class);

interface MyBinderWidgetUiBinder extends UiBinder { }

@UiField VerticalPanel myPanelContent;

public MyBinderWidget() {
initWidget(uiBinder.createAndBindUi(this));

HTML html1 = new HTML();
html1.setHTML("Click me!");
myPanelContent.add(html1);
HTML html2 = new HTML();
html2.setHTML("This is my sample content!");
myPanelContent.add(html2);

}

}


Now change the entry point class to look like the following.


package com.jeffdouglas.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;

public class HelloUiBinder implements EntryPoint {

public void onModuleLoad() {
MyBinderWidget w = new MyBinderWidget();
RootPanel.get().add(w);
}
}


Now open HelloUiBinder.html and remove all of the HTML content between the </noscript> and </body> and save it. Once you run the application, copy the development URL and run paste it into your favorite supported browser, you should see the following.



Now suppose you wanted to nest a widget inside your MyBinderWidget that did something when a button was clicked. We’ll create a small series of checkboxes that allows the user to select their favorite colors and display them when the button is clicked. Create a new UiBinder called FavoriteColorWidget in the client package. Add the following code to the FavoriteColorWidget.ui.xml template.





Choose your favorite color(s):
Red
White
Blue
Submit




Now add the click handler in the FavoriteColorWidget.java owner class.


package com.jeffdouglas.client;

import java.util.ArrayList;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;

public class FavoriteColorWidget extends Composite {

private static FavoriteColorWidgetUiBinder uiBinder = GWT
.create(FavoriteColorWidgetUiBinder.class);

interface FavoriteColorWidgetUiBinder extends
UiBinder {
}

@UiField Label greeting;
@UiField CheckBox red;
@UiField CheckBox white;
@UiField CheckBox blue;
@UiField Button button;

public FavoriteColorWidget() {
initWidget(uiBinder.createAndBindUi(this));

// add a greeting
greeting.setText("Hello Jeff!!");

final ArrayList checkboxes = new ArrayList();
checkboxes.add(red);
checkboxes.add(white);
checkboxes.add(blue);

// add a button handler to show the color when clicked
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
String t = "";
for(CheckBox box : checkboxes) {
// if the box was checked
if (box.getValue()) {
t += box.getFormValue() + ", ";
}
}
Window.alert("Your favorite color/colors are: "+ t);
}
});

}

}


The last thing we’ll need to do is add our new widget to the MyBinderWidget template. Open MyBinderWidget.ui.xml and add the custom namespace reference and the FavoriteColorWidget.


;


.bolder { font-weight:bold; }









Now when you run the application it should look like the following.

6 comments:

Ioannis said...

Hi Jeff. The example you posted is great!

Inspired by your Example I made a Panel Composite(A) and with the help of uibinder I added some buttons in it.

I am using this Composite(A) inside an other Composite(B) and I would like to add some more Buttons inside (A) from the ui.xml of (B).

Have you ever tried something similar?

Thanks again for the wonderful example.

JohnBoy said...

Nice. I particularly appreciated the nested component description which is crucial.

PeteUK said...

Are your template files complete? All the XML element names seems to be lowercase, so HTMLPanel has become htmlpanel, etc.

Also, on the root XML element where you have ui="urn:ui:com.google.gwt.uibinder", shouldn't that be xmlns:ui="urn:ui:com.google.gwt.uibinder"?

Thanks for the example!

PeteUK said...

Me again! There's quite a few other errors I've found in just getting step 1 working:

1) Cannot nest VerticalPanel with a Label.
2) Cannot use stylename attribute for Label - it needs to be styleName.
3) Line 33 (last line) of MyWidgetBinder.java shouldn't be there.
4) MyBinderWidgetUiBinder declaration incorrect - cannot use mybinderwidget="" as second generic parameter to superclass.
5) MyBinderWidgetUiBinder declaration incorrect - cannot use widget as first generic parameter to superclass. Must be Widget.
6) Call to html1.setHTML() fails to compile because embedded quotes need to be escaped.

That's quite a lot of errors for something that is supposed to teach newbies!

I'm about to go through step 2 (but I won't post up errors for that). Thanks again for the example!

PeteUK said...

Just completed this. GWT looks really good.

Cheers for the example.

PeteUK said...

For anyone else trying to follow this tutorial, please go to http://blog.jeffdouglas.com/2010/01/19/gwt-uibinder-hello-world-tutorial/ The tutorial there is exactly the same by the same author but doesn't have the problems I mentioned above.

Post a Comment

 
2006-2010 Appirio Inc. All rights reserved.
Appirio.com | Support | Resource Center | Contact | Careers | Privacy Policy