I have a GWT app with one main panel showing a table of PostgreSQL instances. I want the app to show other kinds of instances, e.g. Redis instances. So I'm initially wrapping the main panel in a DeckLayoutPanel to swap out the PostgreSQL panel with a Redis panel. There will a vertical menu on the left side that the user will use to select the type of instance to show.
Adding DeckLayoutPanel to the UI XML causes the main panel to not display, although I do see the content in a DOM inspector.
Here's the original, working UI, without g:DeckLayoutPanel
:
<!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">
<g:HTMLPanel>
<table width="100%" border="1">
<tr>
<td colspan="2" align="left">
<a href="/">Logo</a>
</td>
<td colspan="2" align="right">
Hello John
</td>
</tr>
<tr>
<td colspan="4">
<g:VerticalPanel ui:field="instancesPanel">
<g:Label ui:field="mainErrorLabel" />
<g:FlexTable ui:field="flexTable" />
<g:HorizontalPanel>
<g:TextBox ui:field="createInstanceTextBox" />
<g:ListBox ui:field="createInstanceVersionsListBox" />
<g:Button ui:field="createInstanceButton">Create</g:Button>
<g:Label ui:field="createInstanceErrorLabel" />
</g:HorizontalPanel>
</g:VerticalPanel>
</td>
</tr>
<tr>
<td>Help</td>
<td>About</td>
<td>Contact</td>
</tr>
</table>
</g:HTMLPanel>
</ui:UiBinder>
If I remove the g:HTMLPanel
and also the HTML table, trimming it to, this works:
<!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">
<g:DeckLayoutPanel ui:field="deckLayoutPanel">
<g:VerticalPanel ui:field="instancesPanel">
<g:Label ui:field="mainErrorLabel" />
<g:FlexTable ui:field="flexTable" />
<g:HorizontalPanel>
<g:TextBox ui:field="createInstanceTextBox" />
<g:ListBox ui:field="createInstanceVersionsListBox" />
<g:Button ui:field="createInstanceButton">Create</g:Button>
<g:Label ui:field="createInstanceErrorLabel" />
</g:HorizontalPanel>
</g:VerticalPanel>
</g:DeckLayoutPanel>
</ui:UiBinder>
I'm using an HTML table here since I'm not a front-end designer and I have similar HTML for the non-GWT JSP pages (using a JSTL tag) so want to make sure the GWT and non-GWT pages render the same.
Should I be using something else than a table? Should I switch to div
s for placement instead? Is using a g:DeckLayoutPanel
in an HTML table not supported? How is one supposed to get identical HTML pages for GWT and non-GWT pages if one needs to use only GWT layout widgets?
BTW, I tried using RootPanel and that didn't work either with the HTML page.
I'm binding to it using:
interface Binder extends UiBinder<HTMLPanel, MyWebApp> { }
private static final Binder binder = GWT.create(Binder.class);
@UiField
DeckLayoutPanel deckLayoutPanel;
@UiField
VerticalPanel instancesPanel;
@Override
public void onModuleLoad() {
HTMLPanel outer = binder.createAndBindUi(this);
// Tweak a bunch of settings on the UI elements.
...
RootLayoutPanel.get().add(outer);
deckLayoutPanel.showWidget(instancesPanel);
}
The HTML hosting the page is this:
<!doctype html>
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<html>
<head>
<link type="text/css" rel="stylesheet" href="MyWebApp.css">
<title>MyWebApp</title>
<script type="text/javascript" language="javascript" src="MyWebApp/MyWebApp.nocache.js"></script>
</head>
<body>
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
<noscript>
<div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
Your web browser must have JavaScript enabled
in order for this application to display correctly.
</div>
</noscript>
</body>
</html>
DeckLayoutPanel in a HTMLPanel
The problem is part of the title... The short answer is: Do not nest **LayoutPanels in anything other than a **LayoutPanel unless you set a fixed size for it.
**LayoutPanels are meant for applications that that have a static layout that is defined from the outer to the inner. If you only user **LayoutPanels for the outer layout, it works. In your second code example you noticed exactly this behavior.
A html table works different, it needs it's content to define a size and grow with it. As **LayoutPanels do not grow with their contents, they have a size of 0x0px.
I answered a similar question lately (link). Possibly it answers different aspects of this problem.