jQuery mobile のcheckbox を Wicket で

jQuery mobile<input type="checkbox"Wicket で出力しようとする場合、
複数選択可能とする場合、CheckBoxMultipleChoice を使うと複数選択はできない。
そんな時、以前書いた AbstractCheckBoxModel を継承した自作のモデル、

  http://blog.zaq.ne.jp/oboe2uran/article/391/

  ここで書いた、SelectItemUsingCheckboxModel

これを利用すると実現できる。
jQuery mobile 特有の id 属性に対する label タグの for 属性は、
AttributeModifier をうまく使うことなど工夫すればよい。

以下、Wicket で、出力するHTML
<div data-role="fieldcontain">
  <fieldset data-role="controlgroup">
     <input type="checkbox" name="choice:0:chkbox1" id="choice_3" data-theme="c"/><label for="choice_3">Red</label>
     <input type="checkbox" name="choice:1:chkbox1" id="choice_4" data-theme="c"/><label for="choice_4">Green</label>
     <input type="checkbox" name="choice:2:chkbox1" id="choice_5" data-theme="c"/><label for="choice_5">Blue</label>
  </fieldset>
</div>

これを期待するwicket のhtml
<div data-role="fieldcontain">
   <fieldset data-role="controlgroup">
      <span wicket:id="choice">
         <input type="checkbox" wicket:id="chkbox"/><label wicket:id="label"></label>
      </span>
   </fieldset>
</div>


選択肢を表現するクラスを用意する。このサンプルは、色名と任意の値
public class ColorChoice implements Serializable{
   private String value;
   private String color;
   public ColorChoice(String value,String color){
      this.value = value;
      this.color = color;
   }
   public String getValue(){
      return this.value;
   }
   public String getColor(){
      return this.color;
   }
   // equals と hashCode() を実装する必要あり。
   @Override
   public boolean equals(Object obj){
      if (obj==this) return true;
      if (!(obj instanceof ColorChoice)) return false;
      ColorChoice c = (ColorChoice)obj;
      if (this.value.equals(c.getValue()) && this.color.equals(c.getColor())){
         return true;
      }
      return false;
   }
   @Override
   public int hashCode(){
      int hash = 1;
      hash = hash * 17 + this.value.hashCode();
      hash = hash * 17 + (this.value == null ? 0 : this.value.hashCode());
      hash = hash * 17 + this.color.hashCode();
      hash = hash * 17 + (this.color == null ? 0 : this.color.hashCode());
      return hash;
   }
}

//WebPageクラスのフィールド変数として選択コレクションを用意する
Set<ColorChoice> colors = new HashSet<ColorChoice>();

//選択コレクションを、KistView のpopulateItemで参照できるように、
protected Collection<ColorChoice> getColors(){
   return this.colors1;
}

// ListView に渡す全選択リスト
protected List<ColorChoice> getColorChoiceList(){
   List<ColorChoice> list = new ArrayList<ColorChoice>();
   list.add(new ColorChoice("1","Red"));
   list.add(new ColorChoice("2","Green"));
   list.add(new ColorChoice("3","Blue"));
   return list;
}

// 

ListView<ColorChoice> listview1 = new ListView<ColorChoice>("choice",getColorChoiceList()){
   private int ix=0;
   @Override
   protected void populateItem(ListItem<ColorChoice> item){
      ColorChoice choice = item.getModelObject();
      final String idAttr = getIdAttr();
      CheckBox chk = new CheckBox("chkbox",new SelectItemUsingCheckboxModel<ColorChoice>(choice,getColors()));
      chk.add(new AttributeModifier("id",idAttr));
      chk.add(new AttributeModifier("data-theme","c"));
      item.add(chk);
      item.add(new Label("label",choice.getColor()){
         @Override
         protected void onComponentTag(ComponentTag tag){
            tag.put("for",idAttr);
         }

      });
      this.ix++;
      // ListView の囲みの span タグを出力しないようにする
      item.setRenderBodyOnly(true);
   }
   protected String getIdAttr(){
      return "chkbox_"+Integer.toString(this.ix);
   }

};