I need to insert a [number of] uiBinder-based widgets into another one, at a particular spot. The inserted widget has a somewhat complicated layout, so I am trying to define it in HTML.
referencePanel.add(…) fails with java.lang.IllegalStateException: This widget’s parent does not implement HasWidgets. Don’t know which widget’s parent it’s unhappy about – innerPanel or referencePanel.
If the ReferenceUI object is added to RootPanel, and then it’s added to the bottom of the page. But if it’s added to RootPanel first,
then there is a JavaScriptException Code 3 (HIERARCHY_REQUEST_ERR) when added to referencePanel.
Any suggestions?
public class AppUIDemo extends Composite {
@UiTemplate("AppUIDemo.ui.xml")
interface AppUIDemoUiBinder extends UiBinder<Widget, AppUIDemo> {
}
@UiTemplate("ReferenceUI.ui.xml")
interface ReferenceUIUiBinder extends
UiBinder<Widget, ReferenceUI> {
}
private static AppUIDemoUiBinder uiBinder = GWT
.create(AppUIDemoUiBinder.class);
private static ReferenceUIUiBinder refUIBinder = GWT
.create(ReferenceUIUiBinder.class);
@UiField
FlowPanel referencePanel;
public AppUIDemo() {
initWidget(uiBinder.createAndBindUi(this));
ReferenceUI reference = new ReferenceUI(refUIBinder);
HTMLPanel innerPanel = reference.getRefPanel();
innerPanel.getElement().setId(HTMLPanel.createUniqueId());
referencePanel.add(innerPanel);
}
}
public class ReferenceUI extends Composite {
interface ReferenceUIUiBinder extends
UiBinder<Widget,ReferenceUI> {
}
private static ReferenceUIUiBinder uiBinder = GWT
.create(ReferenceUIUiBinder.class);
@UiField
HTMLPanel refPanel;
public ReferenceUI() {
initWidget(uiBinder.createAndBindUi(this));
}
public CreditReferenceUI(final UiBinder<Widget, CreditReferenceUI> binder) {
initWidget(binder.createAndBindUi(this));
}
public HTMLPanel getRefPanel() {
return refPanel;
}
}
ReferenceUI.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"
xmlns:gwittir="urn:import:com.totsp.gwittir.client.ui">
<g:HTMLPanel ui:field="referencePanel">
<table>
<tr>
<td>
<b>First Name</b></td>
<td>
<b>Last Name</b></td>
<td>
<b>Phone</b></td>
<td>
<b>Fax</b></td>
</tr>
<tr>
<td>
<gwittir:TextBox ui:field="referenceFirstName" styleName="input"/></td>
<td>
<gwittir:TextBox ui:field="referenceLastName" styleName="input"/></td>
<td>
<table><tr>
<td> ( </td> <td>
<gwittir:TextBox ui:field="referencePhoneAreaCode" styleName="input" maxLength="3"/></td>
<td> ) </td> <td>
<gwittir:TextBox ui:field="referencePhoneNumber" styleName="input" maxLength="7"/></td>
<td> # </td> <td>
<gwittir:TextBox ui:field="referencePhoneExtension" styleName="input" maxLength="25"/></td>
</tr></table></td>
<td>
<table><tr>
<td> ( </td> <td>
<gwittir:TextBox ui:field="referenceFaxAreaCode" styleName="input" maxLength="3"/></td>
<td> ) </td> <td>
<gwittir:TextBox ui:field="referenceFaxNumber" styleName="input" maxLength="7"/></td>
</tr></table></td>
</tr>
<tr>
<td style="text-align:right">
<b>Address: </b> Street</td>
<td>
<gwittir:TextBox ui:field="referenceStreet" styleName="input"/></td>
<td colspan="2" style="width:50%">
<table><tr><td> City</td>
<td><gwittir:TextBox ui:field="referenceCity" styleName="input" maxLength="25"/></td>
<td> State </td>
<td class="state"><gwittir:TextBox ui:field="referenceState" styleName="input" maxLength="2"/></td>
<td> ZIP</td>
<td><gwittir:TextBox ui:field="referenceZIP" styleName="input" maxLength="9"/></td></tr></table>
</td>
</tr>
</table>
</g:HTMLPanel>
</ui:UiBinder>
AppUIDemo.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"
xmlns:gwittir="urn:import:com.totsp.gwittir.client.ui">
<g:HTMLPanel ui:field="basePanel">
<!-- <div id="MainContent"> -->
<p><h2><b>Application Demo</b></h2></p>
<g:FlowPanel ui:field="referencePanel">
</g:FlowPanel>
</g:HTMLPanel>
</ui:UiBinder>
I’ll start with the fix, then move on to explain it afterward.
Fixing the problem
The easiest way to fix this problem is as follows. Here’s your code:
Replace that with the following code. Note that only the last line has changed.
This way, you are adding the
Compositeobject. There will be no difference to the user, as theHTMLPanel(yourinnerPanel) will be directly attached into the document.Some background
Adding a widget to a complex panel
When you add a widget to a complex panel (a panel that holds more than one child widget), four things happen one after the other:
Telling a widget to remove itself from its parent
When a child is told to remove itself from its parent, one of the following occurs:
HasWidgets, the widget tells the panel to remove that widgetIllegalStateExceptionwith message “This widget’s parent does not implement HasWidgetsComposite widgets
When calling
initWidget(Widget), the widget’s parent is set to theCompositeobject.The problem
When you try to add
innerPanel, it is told to remove itself from its current parent.innerPanelis actually the root of your UiBinder template. Its parent is aCompositeobject (specifically,ReferenceUI). This results in the exception being thrown, asCompositedoes not implementHasWidgetsand does not support removing its widget.