Sencha Inc. | HTML5 Apps

Ext GWT 3 Declarative Markup with UiBinder

Published Sep 19, 2011 | Justin Hickman | Tutorial | Medium
Last Updated Oct 18, 2011

This Tutorial is most relevant to , 3.x.

Intro

The GWT 2.0 release introduced the ability to construct user interfaces in a declarative way using XML files. To support UiBinder in Widgets, several conventions had to be followed. These include implementing HasWidgets to allow a Widget to behave as a container, implementing HasHTML to allow raw HTML directly in panels, and adding @UiConstructor and @UiChild annotations in Widgets to support custom behavior.

Ext GWT 2 was released prior to GWT 2.0 and thus did not have support for UiBinder. UiBinder support has been one of the major driving factors for many of the API changes in Ext GWT 3.0.

Here is a very simple example of a UiBinder template containing Ext GWT 3.0 Widgets:

<ui:UiBinder
xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:gxt="urn:import:com.sencha.gxt.widget.core.client"
xmlns:button="urn:import:com.sencha.gxt.widget.core.client.button">
 
<gxt:FramedPanel collapsible="true" headingText="Example" pixelSize="100, 80">
  <button:TextButton ui:field="exampleButton" text="Click Me" />
</gxt:FramedPanel>
 
</ui:UiBinder>

You can see in this example that the FramedPanel is a container that may hold child Widgets.

Here’s a more complex example that shows the construction of a MenuBar.

<ui:UiBinder
  xmlns:ui='urn:ui:com.google.gwt.uibinder'
  xmlns:gxt="urn:import:com.sencha.gxt.widget.core.client"
  xmlns:menu="urn:import:com.sencha.gxt.widget.core.client.menu">a
 
  <ui:style>
    .menuBorder { border-top: none; }
  </ui:style>
 
  <gxt:ContentPanel headingText="MenuBar Example" pixelSize="400, 300">
    <gxt:TopBottomComponent>
      <gxt:topwidget>
        <menu:MenuBar borders="true" addStyleNames="{style.menuBorder}">
          <menu:MenuBarItem text="File">
            <menu:menu>
              <menu:Menu>
                <menu:MenuItem text="New" ui:field="newFile" />
                <menu:MenuItem text="Open File">
                  <menu:submenu>
                    <menu:Menu>
                      <menu:MenuItem text="readme.txt" />
                      <menu:MenuItem text="helloworld.txt" />
                    </menu:Menu>
                  </menu:submenu>
                </menu:MenuItem>
              </menu:Menu>
            </menu:menu>
          </menu:MenuBarItem>
        </menu:MenuBar>
      </gxt:topwidget>
    </gxt:TopBottomComponent>
  </gxt:ContentPanel>
</ui:UiBinder>

This example shows Widgets nested several levels deep. This nesting will aid development such that the developer can quickly understand and visualize the menu hierarchy. This allows faster design and development of more complex structures.

Event Handling

Ext GWT 3.0 also includes many changes to the Event model to conform to the GWT approach. By following these conventions, event handling methods for widgets in the UiBinder can be written in the owner class. These methods are annotated with @UiHandler and receive events on child Widgets, just like in GWT. This greatly simplifies the ability to add event handlers. It also adds a clear separation of layout logic versus actions.

To build on the above MenuBar example, we can use the MenuItem containing the ui:field attribute to apply a SelectionHandler in the owning class.

public class MenuBarUiBinderExample implements IsWidget, EntryPoint {
 
  interface MyUiBinder extends UiBinder<Widget, MenuBarUiBinderExample> {
  }
 
  private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
 
  public Widget asWidget() {
    return uiBinder.createAndBindUi(this);
  }
 
  public void onModuleLoad() {
    RootPanel.get().add(asWidget());
  }
 
  @UiHandler("newFile")
  public void onNewFile(SelectionEvent<Item> event) {
    Info.display("New File", "You have clicked on the New File MenuItem");
  }
}

UiBinder Extension

Many layout containers in Ext GWT 3.0 use LayoutData objects to aid in styling child Widgets. For the BorderLayoutContainer, this is done by calling methods such as setNorthWidget(IsWidget, BorderLayoutData);.

Fortunately, with the use of the @UiChild annotation, we can construct UiBinder XML such as this:

<container:BorderLayoutContainer>
  <container:north layoutData="{northLayoutData}">
    <button:TextButton />
  </container:north>
</container:BorderLayoutContainer>

GWT, however, does not provide any built-in mechanisms for creating arbitrary objects in the UiBinder XML. To make the northLayoutData field available in the UiBinder XML, we must use a combination of @UiField in the owner class and <ui:with> element in the XML.

@UiField(provided=true)
BorderLayoutData northLayoutData = new BorderLayoutData(100);
 <ui:with type="com.sencha.gxt.widget.core.client.container.BorderLayoutContainer.BorderLayoutData"
        field="northLayoutData" />

It’s not always convenient to construct these objects in the owner class. In some organizations where separate teams write the Java code and the UiBinder XML, it may not be ideal to distribute, what is considered view logic/data, across the Java class and the XML file.

To remedy this situation, Ext GWT 3.0 is introducing an extension to the UiBinder <ui:with> element to allow complete construction of non Widget types for cases just like this. This UiBinder extension is contained in a separate JAR. This will allow organizations to choose whether or not this solution is a viable option for their projects.

In this example, you can see that <ui:with> now supports a child element called <ui:attributes>. This is used to provide constructor arguments (assuming a class with a @UiConstructor annotation) and property values.

<ui:UiBinder
  xmlns:ui="urn:ui:com.google.gwt.uibinder"
  xmlns:container="urn:import:com.sencha.gxt.widget.core.client.container">
 
  <ui:with type="com.sencha.gxt.widget.core.client.container.BorderLayoutContainer.BorderLayoutData"
           field="northLayoutData">
    <ui:attributes size="100" />
  </ui:with>
 
  <container:BorderLayoutContainer>
    <container:north layoutData="{northLayoutData}">
      <button:TextButton />
    </container:north>
  </container:BorderLayoutContainer>
 
</ui:UiBinder>

Fields declared in <ui:with> elements can also refer to other fields:

<ui:UiBinder
  xmlns:ui="urn:ui:com.google.gwt.uibinder"
  xmlns:container="urn:import:com.sencha.gxt.widget.core.client.container">
 
  <ui:with type="com.sencha.gxt.core.client.util.Margins" field="northMargins">
    <ui:attributes top="0" right="0" bottom="5" left="0" />
  </ui:with>
 
  <ui:with type="com.sencha.gxt.widget.core.client.container.BorderLayoutContainer.BorderLayoutData"
           field="northLayoutData">
    <ui:attributes size="100" margins="{northMargins}" />
  </ui:with>
 
  ...
 
</ui:UiBinder>

Summary

With Ext GWT 3.0, you will be able to quickly and easily build application interfaces declaratively using UiBinder. Constructing and assembling Ext GWT Widgets is just as easy as building most GWT widgets, and with some proposed changes to uibinder, complex layouts are just as easily supported. We look forward to seeing what the Ext GWT community will be able to produce with these new tools, made stronger with advanced layouts.

Share this post:
Leave a reply

Written by Justin Hickman
Justin Hickman is a developer for Ext GWT. He is very passionate about Java development. He has worked on several large GWT applications and has created open source frameworks such as gwt-customuibinder and gxt-uibinder.

3 Comments

Viacheslav Dobromyslov

3 years ago

It works fine when I run application but I can’t use it with GWTDesigner. The following exception appears when I try to switch from some.ui.xml to the designer tab in Eclipse.

!ENTRY org.eclipse.wb.core 4 4
!MESSAGE Designer [2.4.2.r37x201110181239]: 4108 (Error loading module(s).).    [ERROR] Error occured loading property:
[ERROR] Deferred binding failed for ‘com.sencha.gxt.core.client.GXT.UserAgent’; expect subsequent failures
[ERROR] Failed to create an instance of ‘com.sencha.gxt.widget.core.client.FramedPanel’ via deferred binding

Marcos Mak

3 years ago

I want to use GWTDesigner too! I don’t want to code XML.

giovanni

3 years ago

is there any plan to be compatible with GWTDesigner?

Leave a comment:

Commenting is not available in this channel entry.