GWT: ‘A widget that has an existing parent widget may not be added to the detach list’
GWTのクライアントコンソールに以下のようなエラーが表示された。
Error: java.lang.AssertionError: A widget that has an existing parent widget may not be added to the detach list
GWT: ‘A widget that has an existing parent widget may not be added to the detach list’に説明してくれてる人がいる。
これは既存のDOM要素をGWTウィジェットでラップする時に発生する。例えばButton.wrap(…)、HTML.wrap(…)等など。
分析
GWTでは不可能のようだ。ドキュメントのDOMについて、その親のいずれかが既にGWTウイジェットでラップされている場合、その子をラップすることは。例えば、
<div style=”display: none” id=“outer_element”>
<form class=“well”>
<label><i class=“icon-exclamation-sign”></i> An error occurred while requesting your API key.</label>
<div id=“inner_element”>No error message.</div>
</form>
</div>
この状態で以下を行う。
HTML errorForm = HTML.wrap(DOM.getElementById(“outer_element”));
Label errorMessage = Label.wrap(DOM.getElementById(“inner_element”));
すると、inner_elementの時点でエラーが発生する。outer_elementが既にラップされているからだ。
解決策
単純に内から外にラップしていけば、エラーを避けることができる。上の場合は、単純にラップの順序を逆転する。
Label errorMessage = Label.wrap(DOM.getElementById(“inner_element”));
HTML errorForm = HTML.wrap(DOM.getElementById(“outer_element”));
参照
- gwt – How to add a custom widget to an element – Stack Overflow
- How to wrap an existing div into an HTML widget ? – Google Web Toolkit | Google
- java – How to mix html with gwt widgets? – Stack Overflow
より詳細な分析
どのElementでも同じなのだが、例えばAnchor.wrap(…)を呼び出す。これは以下のコードになっている。
public static Anchor wrap(Element element) {
// Assert that the element is attached.
assert Document.get().getBody().isOrHasChild(element);
Anchor anchor = new Anchor(element);
// Mark it attached and remember it for cleanup.
anchor.onAttach();
RootPanel.detachOnWindowClose(anchor);
return anchor;
}
エラーは最後のRootPanel.detachOnWindowClose(anchor)で発生している。
RootPanel.detachOnWindowClose(…)の機能としては、detach Listというもののメンテナンスなのだが、これはgwt detach listに説明がある。