はじめに
JSF の <h:selectManyCheckbox>
タグは使わずに、<h:selectBooleanCheckbox>
タグで代替しましょう という話です。
selectManyCheckbox タグ
JSF の HTML BASIC タグである selectManyCheckbox
のレンダリング結果は HTML のテーブルとして展開されます。
バッキングビーンで以下のようなプロパティがあったとします。
private List<Item> selectItems; private List<Long> selectedIds;
selectItems
が選択肢、selectedIds
にチェックボックスの選択対象を受ける場合、テンプレートでは selectManyCheckbox
タグを使って以下のようになります。
<h:selectManyCheckbox value="#{backing.selectedIds}"> <f:selectItems value="#{backing.selectItems}" var="_var" itemLabel="#{_var.name}" itemValue="#{_var.id}" /> </h:selectManyCheckbox>
出力は以下のようになります。
この場合のレンダリング結果は、以下のようにテープルを使った HTML となります。
<table> <tr> <td> <input name="form:j_idt29" id="form:j_idt29:0" value="1" type="checkbox" /> <label for="form:j_idt29:0" class="">check item 1</label> </td> <td> <input name="form:j_idt29" id="form:j_idt29:1" value="2" type="checkbox" /> <label for="form:j_idt29:1" class="">check item 2</label> </td> </tr> </table>
チェックボックスは横方向に列挙するような固定レイアウトが強要されます。
テンプレートには現れないテーブルが勝手に生成されるため、スタイルの割当がやりにくく、とても使いにくいものになります。
selectBooleanCheckbox タグで代替する
標準レイアウトが望ましくない場合は、selectManyCheckbox
ではなく、selectBooleanCheckbox
タグを使い <ui:repeat>
してあげるのが良いです。
バッキングビーン側は以下のように Map で受ける形にします。
private List<Item> selectItems; private Map<Long, Boolean> selectedIds;
テンプレートは以下のような定義になります。
<ui:repeat value="#{backing.selectItems}" var="_var"> <h:selectBooleanCheckbox id="ids" value="#{backing.selectedIds[_var.id]}" /> <h:outputLabel for="ids" value="#{_var.name}" /> </ui:repeat>
しかし今どきであれば、HTML5-Friendly Markup を使うことになるでしょう。
HTML5-Friendly Markup
JSF 2.2 から導入された HTML5-Friendly Markup により、先のテンプレートは、スタイルも当てて以下のように書くことができます。
<ui:repeat value="#{backing.selectItems}" var="_var"> <div class="form-check"> <input class="form-check-input" type="checkbox" jsf:id="ids" jsf:value="#{backing.selectedIds[_var.id]}"/> <label class="form-check-label" jsf:for="ids">#{_var.name}</label> </div> </ui:repeat>
<input type="checkbox">
タグの中に jsf:
で装飾した属性があれば、<h:selectBooleanCheckbox>
として解釈されます。
出力結果は以下のようになります(ここでは Bootstrap のスタイルを当てています)。
<div class="form-check"> <input id="form:j_idt29:0:ids" name="form:j_idt29:0:ids" type="checkbox" class="form-check-input" /> <label for="form:j_idt29:0:ids" class="form-check-label">check item 1</label> </div> <div class="form-check"> <input id="form:j_idt29:1:ids" name="form:j_idt29:1:ids" type="checkbox" class="form-check-input" /> <label for="form:j_idt29:1:ids" class="form-check-label">check item 2</label> </div>