f:selectItem(s)で列挙値を使用する方法


103

質問のステータスを選択できるように、selectOneMenuドロップダウンを作成します。列挙型の順序が変更され、リストが大きい場合にどうなるかを考慮して、f:selectItemをより柔軟にすることは可能ですか?そして、私はこれをもっとうまくできるでしょうか?そして、質問のある項目を自動的に「選択」することは可能ですか?

列挙型クラス

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>

回答:


210

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をたまたま使用する場合<o:importConstants>は、Beanの代わりに使用できます。

<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

BalusCの1つは、質問のデフォルトのステータスを「選択」/表示できることです(たとえば、質問を編集しているときに、質問のステータスをすでに何かに設定しています)
LuckyLuke

上記の例では、JSFは#{bean.question.status}有効なenum値を持っている場合にデフォルトでそれを実行します。にquestion適切なステータスプロパティが事前に入力されていることを確認する必要はありません。
BalusC 2011

@BalusC JSFから序数値にアクセスする方法は?
jacktrades 2013

2
私のように、の数値形式の例外が発生した+= status場合は.concat(status)、@ Ziletkaの提案どおりに使用してみてください。
whistling_marmot 2016年

java.util.Listを使用する場合は、getStatuses()の戻り値の型をList <Status>に変更して、Arrays.asList(Status.values());を返すだけです。
stakahop

16

ローカリゼーションには、このソリューションも使用できます。

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にハードコードされていません。


1
この構文は、「比較的」新しいEL 2.2以降でのみサポートされていることに注意してください。それ以外の場合は、カスタムEL関数をいつでも取得<c:set>または<ui:param>自作できます。
BalusC 2012

BalusCに感謝します。バッキングBeanを使用せずに、どういうわけか#{data.statuses}を列挙クラスに置き換えることは可能ですか(例value = "#{org.myproject.Status.values}")?
Ziletka

@BalusCよろしいですか?GF 3.1.2(Mojarra JSF 2.1.6)を使用しています。
ジレトカ

4

enumをラップするインスタンスの<f:selectItems value="#{carBean.carList}" />リストを使用して返すことができます SelectItemStatus.values()可能なすべての値を取得するために使用)。


2

次のユーティリティ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)


「関数」の必要はありません(メソッドの詳細)#{myBundle[enumName.i18nKey]}。i18nキーを使用してプロパティとして列挙型に入れることができる場合:BLA_TYPE("SOME_BLA_TYPE_KEY")by BLA_TYPEは使用する列挙型SOME_BLA_TYPE_KEYで、i18nキーです。
Roland
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.