GWT UI Binder using pure HTML - gwt

Is there a way to work with pure HTML in GWT UIBinder.
The problem I am seeing is more of where we have to wrap the style in curly braces. Any link /article/book handling UIBinder in detail would be helpful.
I have already seen the articles in GST website

The style name (CSS class name) must be put in curly braces, e.g. <div class="{style.example}">...</div>, when the name is obfuscated by GWT. GWT does this, when you use a CssResource. This is also the case, when you declare it in a <ui:style> block in your .ui.xml file:
<ui:UiBinder ...>
<ui:style>
.example {
...
}
</ui:style>
<div class="{style.example}">
...
</div>
</ui:UiBinder>
In contrast, when you declare your CSS class in a plain CSS file (which you directly reference form you HTML host page), then you don't put the name in curly braces. In that case, you just use it like
<ui:UiBinder ...>
<div class="example">...</div>
</ui:UiBinder>

You can use it this way which is close to pure HTML:
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
ui:generateLocales="default"
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<ui:style>
... CSS ...
</ui:style>
<g:HTMLPanel>
... HTML and GWT controls ...
</g:HTMLPanel>
</ui:UiBinder>

I've been looking for the answer to this question via google and landed here.
I've found the solution that worked for me here:
http://blog.sortedset.com/googles-app-engine-java/gwt-uibinder-helloworld-with-html/
The essentials:
Use
interface MyUiBinder extends UiBinder<Element, MobileUI>
instead of
interface MyUiBinder extends UiBinder<Widget, MobileUI>
Use
setElement(uiBinder.createAndBindUi(this));
instead of
initWidget(uiBinder.createAndBindUi(this));
Use
RootPanel.getBodyElement().appendChild(myUiBinder.getElement());
instead of
RootPanel.get().add(myUiBinder);

Related

How to use buttons with GWT's UiBinder?

In MyPanel.ui.xml:
<button class="btn" ui:field="myButton">Save</button>
In MyPanel.java:
public class MyPanel extends Composite {
...
#UiField ButtonElement myButtonUi;
...
public MyScreen() {
final HTMLPanel panel = uiBinder.createAndBindUi(this);
initWidget(panel);
Button myButton = Button.wrap(myButtonUi);
In MyEntryPoint.java:
if (....)
RootPanel.get().add(new MyPanel());
So I think I don't really understand how to use UiBinder.
It's my intention to use HTML with ui:field=".." so that the web-designer can set things like class="xx" on the UI fields. Most of the GWT documentation assumes you've got a Button not a ButtonElement. But if I use a Button I need to have a <g:Button> in the HTML document which means my web-designer can't set the class? I mean the point of UiBinder is to allow one to use normal HTML and integrate it with the GWT code?
When I do the above, on the wrap line, I get a NullPointerException in development mode from:
public static Button wrap(com.google.gwt.dom.client.Element element) {
// Assert that the element is attached.
assert Document.get().getBody().isOrHasChild(element);
In production mode it seems to work OK. In the debugger of development mode in Eclipse, when I right-click and "Inspect" the expression "Document.get().getBody()" Eclipse says "Cannot send a static message to a non class type object".
What should I do? Is the null pointer exception happening because I need to attach the element first? If so, how? (I am already calling createAndBindUi and the element passed to wrap is non-null).
So finally, here's the answer. I Edited it and deleted useless comments.
You can't use HTML in your ui.xml if your plan is to use UiBinder to wire a component from the ui.xml to your view's Java code. Instead of
<button class="btn" ui:field="myButton">Save</button>
use
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<g:Button styleName="btn" text="Save" ui:field="myButton"/>
Then in your view -java code- simply type
#UiField com.google.gwt.user.client.ui.Button myButton;
public MyScreen() {
final HTMLPanel panel = uiBinder.createAndBindUi(this);
initWidget(panel);
}
That's it.
The "styleName" attribute is enough for your designer to hook a CSS class. This other post might interest you. Designers will have to learn about what attributes are available on which components. Using UiBinder is not as straighforward as using HTML.
UiBinder is not for writing HTML but to write XML that can be understood by GWT and compiled to javascript (which in turn will produce the page's HTML). It's not like the JSP mechanism where you can insert plain HTML right away.
UiBinder is most helpful when you have to wire ui elements (widgets or composites from the ui.xml) with your Java view code (i.e. using the #UiField or #UiHandler annotations).
You can use HTML. The only restriction is that g:Button must be inside a container like g:HTMLPanel.
The good thing about g:HTMLPanel is that it can render HTML.
See the example below:
<g:HTMLPanel>
<div>
test
</div>
<table border="1">
<th>
button
</th>
<tr>
<td>
<g:Button styleName="{style.important}" ui:field="button"/>
</td>
</tr>
</table>
<div>
test
</div>
</g:HTMLPanel>

Defining GWT CellTables with UiBinder

If I define my CellTable in MyView.ui.xml UiBinder file like this:
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:c="urn:import:com.google.gwt.user.cellview.client"
ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys='com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator'
ui:generateLocales='default' xmlns:p1="urn:import:com.google.gwt.user.cellview.client">
...
<g:HTMLPanel>
<c:CellTable
addStyleNames='{style.cellTable}'
pageSize='15'
ui:field='cellTable' width="100%">
</c:CellTable>
</g:HTMLPanel>
and then programmaticaly add the columns to the CellTable, everything works fine.
But in an attempt to reduce boilerplate code I would like to define also the table columns in my UiBinder file. I've tried this:
...
<g:HTMLPanel>
<c:CellTable
addStyleNames='{style.cellTable}'
pageSize='15'
ui:field='cellTable' width="100%">
<c:TextColumn
addStyleNames='{style.titleColumn}'
ui:field="titleColumn"/>
</c:CellTable>
</g:HTMLPanel>
But it produces the following error:
[ERROR] [dialective] - Found unexpected child element Element addStyleNames='{style.titleColumn}'ui:field='titleColumn'> (:33)
How could I define the whole CellTable using UiBinder?
Evidently, in the second listing you're trying to add a column as a child object. Cell table doesn't accept children directly (meaning there is no addChild(...) method).
If you have fixed number of columns and want to use UIBinder consider using mere HTML table. In that case you will have all columns in the XML file, but the table will become harder to work with - HtmlElement not Widget.
<table ui:field="table">
<col ui:field="firstColumn" class="{style.firstColumn}">
<col ui:field="secondColumn" class="{style.secondColumn}">
...
</table>
And the code might look like the following
...
#UiField
private TableColElement firstColumn;
#UiField
private TableColElement secondColumn;
But all other operations with the table will be via DOM. Like table.appentChild(rowElement). I think doing like this doesn't worth it.

How to implement i18n in GWT application?

I have a problem with internationalization. I'm trying to implement support two languages ​​in my GWT application. Unfortunately I never found a complete example how to do it with the help of UiBinder. That is what I did:
My module I18nexample.gwt.xml:
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='i18nexample'>
<inherits name="com.google.gwt.user.User" />
<inherits name='com.google.gwt.user.theme.clean.Clean' />
<inherits name="com.google.gwt.i18n.I18N" />
<inherits name="com.google.gwt.i18n.CldrLocales" />
<entry-point class='com.myexample.i18nexample.client.ExampleI18N' />
<servlet path="/start" class="com.myexample.i18nexample.server.StartServiceImpl" />
<extend-property name="locale" values="en, fr" />
<set-property-fallback name="locale" value="en" />
</module>
My interface Message.java:
package com.myexample.i18nexample.client;
import com.google.gwt.i18n.client.Constants;
public interface Message extends Constants {
String greeting();
}
The same package com.myexample.i18nexample.client has three properties file:
Message.properties:
greeting = hello
Message_en.properties:
greeting = hello
Message_fr.properties:
greeting = bonjour
My UiBinder file Greeting.ui.xml:
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
ui:generateFormat="com.google.gwt.i18n.rebind.format.PropertiesFormat"
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
ui:generateLocales="default" >
<ui:with type="com.myexample.i18nexample.client.Message" field="string" />
<g:HTMLPanel>
<ui:msg key="greeting" description="greeting">Default greeting</ui:msg>
</g:HTMLPanel>
</ui:UiBinder>
When the application starts, I always get the output in the browser:
Default greeting
Why? What am I doing wrong?
I tried to run the application from different URL:
http://127.0.0.1:8888/i18nexample.html?gwt.codesvr=127.0.0.1:9997
http://127.0.0.1:8888/i18nexample.html?locale=en&gwt.codesvr=127.0.0.1:9997
http://127.0.0.1:8888/i18nexample.html?locale=fr&gwt.codesvr=127.0.0.1:9997
The result does not change. Although I expected in last case a message bonjour.
If for example I use a g:Buttton instead of the message ui:msg:
<g:HTMLPanel>
<g:Button text="{string.greeting}" />
</g:HTMLPanel>
Then I get as a result of the button with text "hello"
And if I enter the URL:
http://127.0.0.1:8888/i18nexample.html?locale=fr&gwt.codesvr=127.0.0.1:9997
The text on the button changes to "bonjour". Here everything works as expected. But why internationalization is not working in my first case?
And whether there is a difference between the following:
<ui:msg description="greeting">Default greeting</ui:msg>
<ui:msg description="greeting">hello</ui:msg>
<ui:msg description="greeting"></ui:msg>
Should there be different results in these cases? How to write properly?
Please explain to me the principles of internationalization in GWT and why my example does not work.
Any suggestions would be greatly appreciated.
First, the files should be named Message_fr.properties (resp. Message_en.properties), not Message.properties_fr (resp. Message.properties_en).
Then ui:msg et al. in UiBinder will generate an interface (extending com.google.gwt.i18n.client.Messages)), not use one that you defined. For that, you have to use {string.greeting} (where string is the ui:field you gave to your ui:with). The UiBinder generator will do a GWT.create() on the type class of your ui:with, which is what you'd have done in Java code:
Message string = GWT.create(Message.class);
String localizedGreeting = string.greeting();
In the implicit Messages interface (generated by UiBinder), the various ui:generateXxx attributes on the ui:UiBinder will be transformed into annotations on the interface (properties of the #Generate annotation, or the value of the #GenerateKeys annotation).
Then, one method will be generated for each ui:msg, where the attributes generate equivalent annotations (#Key, #Description) and the content of the ui:msg element is the value of the #DefaultMessage annotation. When you have or widgets inside the content, they'll be turned into arguments to the method and placeholders in the #DefaultMessage text (the values will be filled by UiBinder).
I'd suggest you make something working without UiBinder first, and understand how it works; then try the ui:msg in UiBinder, using -gen in DevMode or the compiler so you can see exactly what code does UiBinder generate (yes, it really only generates code that you could have written yourself by hand).
Also, you should add a <set-property name="locale" value="en, fr" /> or you'll still have the default locale around, despite the set-property-fallback (it'd just never be used)).

CSS class definition doesn't work inside <g:HTML> element

Could you guys tell me why css class definition doesn't work in following example ?
I'm using GWT 2.4 + Chrome 17.
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<ui:style>
div.test {
color: red;
}
</ui:style>
<g:HTML>
<div class="test">I should be red but I'm not</div>
</g:HTML>
</ui:UiBinder>
CSS classes listed in the <ui:style> will be obfuscated, going from test to GKYSKJX (or something similar).
Update your div to this:
<div class="{style.test}">Now I'm red :)</div>
Alternatively, you could choose to force your style to NOT obfuscate by doing this:
#external .test;
div.test {
color: red;
}
Unless you have a good reason, I recommend sticking with the first method.
See more at Declarative Layout with UiBinder - Hello Stylish World.

Grid + UiBinder : Setting row level styles

...........
.........
<g:row styleName="OddNumberRow">
....
....
</g:row>
<g:row styleName="EvenNumberRow">
....
....
</g:row>
...........
...........
The above approach is not working. In other words, the "tr" elements in the generated html do not have any class names at all. A back up option would be to inject styles into these rows from the UiBinder's constructors (using getRowFormatter.addStyleName) but
I do not want to take that route for now.(I wanna try to reserve the code that goes into the UiBinder java class for event handling purposes only. )
Any thoughts/pointers would be much appreciated.
Note: Cross posted at https://groups.google.com/forum/?fromgroups#!topic/google-web-toolkit/yGRUkpcpBzU
thanks
You are right, this does not work. I have also tried adding the style to g:customCell, which does not work either.
The only way I can think of is using a SimplePanel to wrap your content in:
<g:row>
<g:customCell>
<g:SimplePanel width="100%" height="100%" styleName="OddNumberRow">
<g:Label>Content</g:Label>
</g:SimplePanel>
</g:customCell>
</g:row>
<g:row>
<g:customCell>
<g:SimplePanel width="100%" height="100%" styleName="EvenNumberRow">
<g:Label>Content</g:Label>
</g:SimplePanel>
</g:customCell>
</g:row>
It looks like GWT has been updated to understand styleName=foo directly on <gwt:cell> and <gwt:row> elements.
Your example code should now do what you expect :)