1. はじめに
Javaのenumは定数と異なりタイプセーフで、かつ、複数のデータを持つことが出来る便利なデータ型です。そのため、マスタなどのコードとその意味を一緒に定義することができます。
今回はJSPでそのenumを利用して、簡単にリストボックスやチェックボックスを表示する方法について説明したいと思います。
Webアプリはspring-boot(spring mvc、TERASOLUNA5.x)の前提とします。
2. enumの定義
今回のサンプルで利用するenumを定義します。intのcode
フィールドと表示するlabel
フィールドのデータを持つenumとしました。
lombokを利用しない場合は明示的にコンストラクタとセッターも定義してください。
package com.example.demo;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum Status {
APPROVAL(1, "承認"),
DENIAL(2, "否認"),
WITHDRAWAL(3, "取り下げ");
int code;
String label;
// ★ポイント1
public String getName() {
return name();
}
}
★ポイント1
enumはname()
というメソッドを持っていますが、ゲッターとしてアクセスしたいため、ラップしたgetName()
メソッドを定義します。
JSPでenumを利用するための対策です。
3. Formクラスの定義
入力されたデータを格納するFormクラスを定義します。
public class DemoForm implements Serializable {
// ★ポイント2
@NotNull
Status status;
// ommited
}
★ポイント2
定義したenumをそのままフィールドとして定義します。intのコードやStringのラベルで受け取る必要はありません。enumはデータ型なので、このフィールドは必ずStatus
となります。
必須項目としたいのでBean Validationの@NotNull
アノテーションを付与しました。
4. enumでリストボックスを出力するJSP
今回の記事のポイントであるenumでリストボックスを出力するJSPを作成します。
JSPの標準機能とspringの機能(<form:xxx />
はspringのタグ)を利用します。
<%-- ★ポイント3 --%>
<%@ page import="com.example.demo.Status" %>
... 省略 ...
<%-- ★ポイント4 --%>
<form:errors path="status"/>
<form:select path="status" items="${Status.values()}" itemLabel="label" itemValue="name" />
★ポイント3
JSPでStatus
を参照したいため<%@ page import="fqcn" %>
でクラスをインポートします。
JSPをスクリプトレットで記述していた時代はよく見かけましたが、最近はあまり見かけませんが、JSPの標準機能です。
★ポイント4
springの<form:select />
タグを利用してリストボックスを出力します。属性が多いのでそれぞれについて以下で説明します。
属性 | 説明 |
---|---|
path |
Formクラスの該当するフィールド名を指定します。今回はstatus になります。 |
items |
リストボックスに表示するデータを格納したコレクションや配列を指定します。 ここでenumの value() スタティックメソッドを呼び出すのがポイントです。このメソッドはenumの配列を返します。これでenumの3項目を表示することができます。 ★ポイント3で Status をインポートしたのは、このスタティックメソッドを呼び出すためです。 |
itemLabel |
リストボックスの表示項目に利用するフィールドを指定します。今回はStatus のlabel フィールドを表示したいのでlabel を指定します。 |
itemValue |
リストボックスの値に利用するフィールドを指定します。code としたくなりますが、ここにname を指定するのがポイントです。レンダリングする際はゲッターを呼び出すことになるので、★ポイント1で定義した getName() メソッドが呼び出されることになります。 |
5. 出力されるリストボックスのHTML
出力されるリストボックスのHTMLを以下に示します。
<option>
のvalue
属性にenumのname
、表示項目にはlabel
が設定されます。
value
がStatus
enumに定義されているname
と一致する値の場合、特別な処理を行うことなくFormクラスにバインドすることが可能になります。
<select id="status" name="status">
<option value="APPROVAL">承認</option>
<option value="DENIAL">否認</option>
<option value="WITHDRAWAL">取り下げ</option>
</select>
value
にenumに定義されていない値(ここではHOGE
)を設定した場合、以下のようにTypeMismatchのエラーとなります。
HTMLのフォームを改ざんしてvalueに不正な値を設定した場合や、★ポイント4のitemValue
で誤ってcode
フィールドを設定した場合などに発生します。
Failed to convert property value of type java.lang.String to required type com.example.demo.Status for property status;
nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String]
to type [com.example.demo.Status] for value HOGE; nested exception is java.lang.IllegalArgumentException: No enum constant com.example.demo.Status.HOGE
ここまでの説明で分かるようにJSPでもenumを利用することで、特別な入力チェックを用意することなく、Formに設定される時点でenumのタイプセーフが適用されます。
6. enumでチェックボックスを出力するJSP
Formクラスは複数選択できるように配列に変更します。
public class DemoForm implements Serializable {
@NotNull
@Size(min = 1, max = 3)
Status[] status;
// ommited
}
リストボックスを出力する際は<form:select />
タグを利用しましたが、チェックボックスの場合は<form:checkboxes />
タグを利用します。
チェックボックスを1つ出力する<form:checkbox />
タグもあるので注意してください。
<%-- ★ポイント5 --%>
<form:errors path="status"/>
<ul>
<form:checkboxes path="status" items="${Status.values()}"
itemLabel="label" itemValue="name" element="li" />
</ul>
★ポイント5
リストボックスと異なるelement
属性について説明します。
これは出力するチェックボックスをラップするHTML要素を指定したい場合に設定します。
今回は<ul><li>
を利用して一覧形式にしようと思いli
を設定しました。
7. 出力されるチェックボックスのHTML
出力されるチェックボックスのHTMLを以下に示します。
チェックボックスのインプットフォームが<li>
タグでラップされています。
<ul>
<li><input id="status1" name="status" type="checkbox" value="APPROVAL"/><label for="status1">承認</label></li>
<li><input id="status2" name="status" type="checkbox" value="DENIAL"/><label for="status2">否認</label></li>
<li><input id="status3" name="status" type="checkbox" value="WITHDRAWAL"/><label for="status3">取り下げ</label></li>
<input type="hidden" name="_status" value="on"/>
</ul>
8. さいごに
今回はJSPでそのenumを利用して、簡単にリストボックスやチェックボックスを表示する方法について説明しました。
今回の方法ではenumの定義を変更してもJSPもFormも修正する必要がありません。
enumを定義する際にgetName()
メソッドを定義するという対策が必要ですが、特別な処理を実装することなく、フォームの入力値を簡単にenumにバインドすることができました。
ぜひJSPでもenumを利用してみてください。