我需要在一个特定的位置插入一个[基于uiBinder的小部件]到另一个小部件。插入的小部件有一个有点复杂的布局,所以我试图用HTML定义它。
referencePanel.add(...)因java.lang.IllegalStateException而失败:此小部件的父级未实现HasWidgets。不知道哪个小部件的父级不满意 - innerPanel或referencePanel。
如果将ReferenceUI对象添加到RootPanel,然后将其添加到页面底部。但如果它首先添加到RootPanel, 然后在添加到referencePanel时有一个JavaScriptException Code 3(HIERARCHY_REQUEST_ERR)。
有什么建议吗?
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>
答案 0 :(得分:13)
我将从修复开始,然后继续解释它。
解决此问题的最简单方法如下。这是你的代码:
HTMLPanel innerPanel = reference.getRefPanel();
innerPanel.getElement().setId(HTMLPanel.createUniqueId());
referencePanel.add(innerPanel);
用以下代码替换它。请注意,只有最后一行已更改。
HTMLPanel innerPanel = reference.getRefPanel();
innerPanel.getElement().setId(HTMLPanel.createUniqueId());
referencePanel.add(reference);
这样,您正在添加Composite
对象。用户没有区别,因为HTMLPanel
(您的innerPanel
)将直接附加到文档中。
将小部件添加到复杂面板(包含多个子窗口小部件的面板)时,会发生四件事情:
当告知孩子从父母身上移走时,会发生以下情况之一:
HasWidgets
的面板的子窗口,则窗口小部件会告诉面板删除该窗口小部件IllegalStateException
,并显示消息“此小部件的父级未实现HasWidgets 调用initWidget(Widget)
时,窗口小部件的父级设置为Composite
对象。
当您尝试添加innerPanel
时,会告知它将其自身从当前父项中删除。 innerPanel
实际上是UiBinder模板的根目录。它的父对象是Composite
对象(具体来说,ReferenceUI
)。这会导致抛出异常,因为Composite
未实现HasWidgets
并且不支持删除其小部件。
答案 1 :(得分:3)
不幸的是,IIRC你不能在UiBinder的代码中为Widget设置一个id(我认为你只能用于普通的HTML)。因此,您只需通过someWidget.getElement().setId()
设置正确的ID(就像您在上面的代码中所做的那样)。
我认为现在缺少的是HTMLPanel referencePanel
中具有正确ID的占位符(div,span,等等),如下所示:
<g:HTMLPanel ui:field="referencePanel">
<div ui:field="referencePanelInner" />
</g:HTMLPanel>
在AppUIDemo
:
@UiField
DivElement referencePanelInner;
// ...
public AppUIDemo() {
// ...
referencePanelInner.setId(reference.getRefPanelId());
}
...除非您想将ReferenceUI直接添加到referencePanel
中 - 在这种情况下,您应该只使用FlowPanel
:)
PS:恕我直言,您应该从ReferenceUI.refPanel
类生成并设置ReferenceUI
的唯一ID(并公开ID) - 这样您就不会弄乱小部件的“内部”来自一些外部小部件。
IllegalStateException
(或ReferenceUI.refPanel
,我不知道哪个是当前名称)添加到ReferenceUI.referencePanel
(AppUIDemo
,因此会引发ReferenceUI
例外显然没有实现HasWidgets
) - 当你应该添加整个ReferenceUI reference
复合词时:)我不知道你为什么这样做首先这样做(也许是因为整个混乱ids),但代码看起来应该是这样的:
public AppUIDemo() {
initWidget(uiBinder.createAndBindUi(this));
ReferenceUI reference = new ReferenceUI(refUIBinder);
referencePanel.add(reference);
}