読者です 読者をやめる 読者になる 読者になる

a repeater and cannot be repainted

Wicket ListView 表示した領域、table 等の表を表示した行をクリックしてモーダルウィンドウを開き
モーダルウィンドウに設置すたフォーム送信を行いモーダルウィンドウを閉じた時に、
元の ListView を再表示したい場合がある。

ListView を setOutputMarkupId(true) を実行して
org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow の setWindowClosedCallback で指定する
WindowClosedCallback の onClose(AjaxRequestTarget target) メソッドオーバーライドで


  target.add( ListViewコンポーネント );

を実行すれば良いと思ったが、以下のようにエラーになる。

java.lang.IllegalArgumentException: Component xxx.xxxx.xxx.XxxxPanel$1 has been added to the target.
This component is a repeater and cannot be repainted via ajax directly.
Instead add its parent or another markup container higher in the hierarchy.

WicketMessage: Method onRequest of interface org.apache.wicket.behavior.IBehaviorListener targeted
at org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow$WindowClosedBehavior@647b865
on component [ModalWindow [Component id = modal]] threw an exception

どうもモーダルウィンドウ表示そのものが AJAX で、それをクローズした時に
ListView で表示したものからモーダルウィンドウ表示の振る舞いを持つのは”繰り返し”ということで
不可能ということらしい。

馬鹿げてるかもしれない解決方法だが、次の方法で解決させることができる。


ListView は、WebMarkContainer で括った Panel の中で表示させる。

<div wicket:id="container">
<div wicket:id="panel"></div>
</div>

wicket:id="panel" の Panel の HTML で ListView 表示する table と ModalWindow の div を設置する。

<wicket:panel>
<table>
   <tbody>
      <tr wicket:id="listview">
         <td wicket:id="id"></td>
         <td wicket:id="username"></td>
      </tr>
   </tbody>
</table>
<div wicket:id="modal"></div>

</wicket:panel>

Panel を表示する Page の HTML ①を書いたHTML では、CSSで display: none を指定したボタンを用意して、

<form wicket:id="form">
<input type="button" wicket:id="review" id="review" style="display: none>
</form>""

  このボタンを AjaxButton(String id, Form<?> form) として設置して
jQueryの方を使うべきと思ったが、
    com.googlecode.wicket.jquery.ui.form.button.AjaxButton.AjaxButton(String id, Form<?> form)
    でも、org.apache.wicket.ajax.markup.html.form.AjaxButton でも、どちらでも可能だった。)

  protected void onSubmit(AjaxRequestTarget target, Form<?> f) のオーバライドで
  ① で設置した WebMarkContainer から、Panale を remove して
  再表示として Panel を生成して WebMarkContainer に add する。

  add した WebMarkContainer をAjaxRequestTarget target の add メソッドで再表示させるようにしておく。


 ②のPanel で、ListView 表示の行をクリックした時に、ModalWindow を表示するように書いたら、
 さらに、ModalWindow の setWindowClosedCallback で指定する WindowClosedCallback
 の onClose(AjaxRequestTarget target) メソッドオーバーライドで
 ③で設置した表示を隠したボタンに対してクリックイベントを発行する。

  target.appendJavaScript("$('#review').trigger('click');");

ちょっとクレイジーかも。