SelectOneMenuドロップダウンを作成して、質問のステータスを選択できるようにします。列挙型の順序が変更された場合、およびリストが大きい場合に何が起こるかを考慮して、f:selectItemをより柔軟にすることは可能ですか?そして、これをもっとうまくできますか?また、質問にあるアイテムを自動的に「選択」することは可能ですか?
Enumクラス
public enum Status {
SUBMITTED,
REJECTED,
APPROVED
}
質問エンティティ
@Enumerated(EnumType.STRING)
private Status status;
JSF
<div class="field">
<h:outputLabel for="questionStatus" value="Status" />
<h:selectOneMenu id="questionStatus" value="#{bean.question.status}" >
<f:selectItem itemLabel="Submitted" itemValue="0" />
<f:selectItem itemLabel="Rejected" itemValue="1" />
<f:selectItem itemLabel="Approved" itemValue="2" />
</h:selectOneMenu>
<hr />
</div>
JSFにはenum
のビルトインコンバーターがあるため、次のようにする必要があります。
@ManagedBean
@ApplicationScoped
public class Data {
public Status[] getStatuses() {
return Status.values();
}
}
と
<h:selectOneMenu value="#{bean.question.status}" >
<f:selectItems value="#{data.statuses}" />
</h:selectOneMenu>
(注:JSF 2.0以降、SelectItem[]
またはList<SelectItem>
を提供する必要がなくなったため、T[]
およびList<T>
も受け入れられ、var
属性によって現在のアイテムにアクセスできます)
JSFユーティリティライブラリ OmniFaces を使用する場合は、Beanの代わりに <o:importConstants>
を使用できます。
<o:importConstants type="com.example.Status" />
<h:selectOneMenu value="#{bean.question.status}" >
<f:selectItems value="#{Status}" />
</h:selectOneMenu>
ラベルも制御する場合は、Status
列挙に追加できます。
public enum Status {
SUBMITTED("Submitted"),
REJECTED("Rejected"),
APPROVED("Approved");
private String label;
private Status(String label) {
this.label = label;
}
public String getLabel() {
return label;
}
}
と
<f:selectItems value="#{data.statuses}" var="status"
itemValue="#{status}" itemLabel="#{status.label}" />
または、より良い方法として、enum値をローカライズされたリソースバンドルのプロパティキーにします(EL 3.0が必要です)。
<f:selectItems value="#{data.statuses}" var="status"
itemValue="#{status}" itemLabel="#{text['data.status.' += status]}" />
リソースバンドル#{text}
に関連付けられたプロパティファイルでこれを使用して
data.status.SUBMITTED = Submitted
data.status.REJECTED = Rejected
data.status.APPROVED = Approved
ローカライズには、このソリューションも使用できます。
public enum Status { SUBMITTED, REJECTED, APPROVED }
data.status.SUBMITTED=Submitted
data.status.REJECTED=Rejected
data.status.APPROVED=Approved
<h:selectOneMenu value="#{bean.question.status}" >
<f:selectItems
value="#{data.statuses}"
var="status"
itemValue="#{status}"
itemLabel="#{text['data.status.'.concat(status)]}" />
</h:selectOneMenu>
そのため、ローカライズ文字列のリソースパスはEnumでハードコーディングされていません。
<f:selectItems value="#{carBean.carList}" />
を使用して、enumをラップするSelectItem
インスタンスのリストを返すことができます(使用可能なすべての値を取得するには、Status.values()
を使用します)。
次のユーティリティel関数を使用して列挙値を取得し、たとえばSelectOneMenu
で使用できます。 Beanと定型メソッドを作成する必要はありません。
public final class ElEnumUtils
{
private ElEnumUtils() { }
/**
* Cached Enumerations, key equals full class name of an enum
*/
private final static Map<String, Enum<?>[]> ENTITY_ENUMS = new HashMap<>();;
/**
* Retrieves all Enumerations of the given Enumeration defined by the
* given class name.
*
* @param enumClassName Class name of the given Enum.
*
* @return
*
* @throws ClassNotFoundException
*/
@SuppressWarnings("unchecked")
public static Enum<?>[] getEnumValues(final String enumClassName) throws ClassNotFoundException
{
// check if already cached - use classname as key for performance reason
if (ElEnumUtils.ENTITY_ENUMS.containsKey(enumClassName))
return ElEnumUtils.ENTITY_ENUMS.get(enumClassName);
final Class<Enum<?>> enumClass = (Class<Enum<?>>) Class.forName(enumClassName);
final Enum<?>[] enumConstants = enumClass.getEnumConstants();
// add to cache
ElEnumUtils.ENTITY_ENUMS.put(enumClassName, enumConstants);
return enumConstants;
}
}
Taglibファイルにel関数として登録します。
<function>
<description>Retrieves all Enumerations of the given Enumeration defined by the given class name.</description>
<function-name>getEnumValues</function-name>
<function-class>
package.ElEnumUtils
</function-class>
<function-signature>
Java.lang.Enum[] getEnumValues(Java.lang.String)
</function-signature>
</function>
そして最後に次のように呼び出します:
<p:selectOneMenu value="#{bean.type}">
<f:selectItems value="#{el:getEnumValues('package.BeanType')}" var="varEnum"
itemLabel="#{el:getEnumLabel(varEnum)}" itemValue="#{varEnum}"/>
</p:selectOneMenu>
BalusCの回答に似ているので、ローカライズされた列挙ラベルを持つリソースバンドルを使用する必要があります。また、よりクリーンなコードのために、getEnumLabel(enum)
のような関数を作成することもできます