Defining GWT CellTables with UiBinder - gwt

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.

Related

How to set Ui:Field name for HTML <tr> tag (not Google Widget)?

I want to set Ui:Field name for HTML tag (not Google Widget), something like this:
in my UiBinder file
<g:HTMLPanel>
<table> <tr ui:field="myRow"><td>Test</td></tr></table>
</g:HTMLPanel>
And my View.java
#UiField Tr myRow;
Can we do this? how to do it properly?
I also want to hide the Tr after clicking hideRow button & how to do that?
In your Java, list it as
#UiField
TableRowElement myRow;
or just as
#UiField
Element myRow;
This is documented at http://www.gwtproject.org/doc/latest/DevGuideUiBinder.html#Hello_World - see the SpanElement called nameSpan or the DivElement called root.
Edit to answer hiding issue added after question was posted:
There isn't a built-in way to hide an Element, but you can manipulate the element in GWT/Java the same as you would in JS, something like this:
myRow.getStyle().setDisplay(Display.NONE);
Other ways to set this include visibility:hidden, or just removing it from its parent element.

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>

Is it possible to set the column width of a grid in GWT using uibinder?

I'm trying to use the GWT grid component in uibinder. It works fine until I want to set the width of the columns. The following is what I've tried to do but it doesn't seem to work.
<g:Grid width="100%">
<g:row>
<g:customCell width="20%">
<g:FlowPanel width="">
</g:FlowPanel>
</g:customCell>
<g:customCell width="80%">
<g:FlowPanel width="">
</g:FlowPanel>
</g:customCell>
</g:row>
</g:Grid>
You can write some java code in order to do that, example:
grid.getColumnFormatter().setWidth(0, "10%");
grid.getColumnFormatter().setWidth(1, "10%");
Only styleName is taken into account on g:row, g:cell and g:customCell elements.
If you can (i.e. if your grid content is mostly static), avoid using Grid and prefer an HTMLPanel containing an HTML <table>, this gives you much more flexibility.
http://code.google.com/p/google-web-toolkit/source/browse/tags/2.4.0/user/src/com/google/gwt/uibinder/elementparsers/GridParser.java

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 :)

GWT UI Binder using pure HTML

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);