tags:

views:

913

answers:

4

Hello,
this is my first post. I hope someone could help me.
I'm looking for a way to define a widget in UiBinder XML layout file separately, without being part of the layout hierachy. Here's a small example:

<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">

<g:Label ui:field="testlabel" text="Hallo" />
<g:HTMLPanel>       
...
</g:HTMLPanel>

The compile fails since the ui:UiBinder element expects only one child element.
In Java Code i will access and bind the Label widget as usual:

@UiField Label testlabel;

For example, this could be useful when you define a Grid or FlexTable - i want to define the Labels for the table header within the XML layout file, not programmatically within the code.

Many thanks in advance

+1  A: 

Sorry, no can do, UiBinder just doesn't support this sort of syntax. Think about it - where would this Widget go? Should it be added to the DOM tree? It also makes it hard for the compiler to tell if this code should be pruned as unused.

You'll have to wait for the GWT team to create custom tags for Grid (like they did with, for example, DockLayoutPanel). I wouldn't expect such functionality for the FlexTable though, since it's meant by design for dynamic content, meaning adding it programmatically anyway.

Igor Klimer
A: 

Thanks for your reply
For sure, it could not be bound to the DOM at runtime, but simply init a widget in code do either. In code i create it first, than i assign all style information to it and then i put it into another widget as a subwidget. Only then it gets part of the DOM.

I just don't understand why a layout concept was introduced, when you are not able to define all your widget there. Another example:
I have a FlexTable in which i will place certain styled Label widgets, or Buttons or whatever. Is there no possibility to define these widgets in the layout file? If this is not so, i think this hole layout xml file concept is incomplete. How do you think?

mr_room
By the way, it's standard practice here to edit your question to respond to feedback, rather than posting an answer.
aem
this should be a comment since its not an answer.
antony.trupe
A: 

Understanding the UiBinder Dev Guide is the key to figuring out how to structure your UiBinder templates cleanly.

So, if all you want to do is create a widget and not have it initially in the DOM, then don't mention it at all in the UiBinder template. Instead, in the Java file that goes with your UiBinder template, create it and add it to a panel that's defined in your template.

For instance, put this in your template:

<g:HTMLPanel ui:field='container'>       
...

And put this in your Java file:

@UiField HTMLPanel container;
public MyWidget() {
  initWidget(uiBinder.createAndBindUi(this));
  Label testLabel = new Label("hallo");
  // Do whatever you want to testLabel
  container.add(testLabel);
}
aem
A: 

I am not certain if you and have the same unusual motivation to place more than two root widgets under the uibinder tag. Anyway, this is how I do it.

Since uibinder tag allows only one root widget, I place an HTML ui tag as the root widget, and then pile up my multiple pseudo-root widgets within that tag.

In the following example, notice that the actual root widget does not have ui:field name, because we don't intend to use it. As far as we are concerned, the effective root widgets are "tabLayout" and "content".

File Hello.ui.xml:

<ui:UiBinder
  xmlns:ui="urn:ui:com.google.gwt.uibinder"
  xmlns:g="urn:import:com.google.gwt.user.client.ui">
  <g:HTML>
    <g:TabLayoutPanel ui:field="tabLayout"  ... >
      blah ... blah
    </g:TabLayoutPanel>
    <g:VerticalPanel ui:field="content">
      blah .. blah
    </g:VerticalPanel>
  </g:HTML>
</ui:UiBinder>

Do not extend composite as your java code behind the template. Create a class imported by your module entrypoint or use the template directly on your module.

I have various reasons why I need more than one root widget. In this example, I attach the "effective root widget" conditionally:

public class Hello
  implements EntryPoint{

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

  interface HelloUiBinder
    extends UiBinder<Widget, Hello>{}

  @UiField TabLayoutPanel tabLayout;
  @UiField VerticalPanel content;

  @Override public void onModuleLoad() {
    uiBinder.createAndBindUi(this);

    if (condition1)
      RootPanel.get().add(tabLayout);
    else
      RootPanel.get().add(content);

    blah ... blah 
  }
}

So, the trick is not to use the actual root widget at all.

Blessed Geek
-1 - because every time you want to use one of those "inner" widgets, you have to create all the others too -> waste of memory. mr_room should just understand that XML/HTML/UiBinder were not meant to be used this way. If you have some elements that you want to add later on, either do it programatically (see libraries like jQuery and such - they don't "put" future HTML tags somewhere in the HTML file, you have to programatically add them) or extract it to a separate Widget/UiBinder template.
Igor Klimer
How expensive is a div tag?
Blessed Geek
It's not *just* a div tag - depending on the widgets, there could be many event handlers, complex schemas, etc. You need to create all of that just to use only a portion - IMHO, that's a waste.
Igor Klimer
I am using all of them in the Java code behind the template. Just snuck everything into one single template. Hate to see so many templates for the same entry point. It's a proliferation of templates that's ugly, arghhh! And, .... and, there is lazy panel for those I don't need yet.
Blessed Geek