如何在f中使用枚举值:selectItem(s)

时间:2011-11-22 15:52:04

标签: jsf jsf-2 enums selectonemenu

我想制作一个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>

4 个答案:

答案 0 :(得分:197)

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}" />

或者,更好的是,将枚举值设为本地化资源包的属性键(需要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

答案 1 :(得分: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中没有硬编码。

答案 2 :(得分:4)

您可以使用<f:selectItems value="#{carBean.carList}" />并返回包含枚举的SelectItem个实例列表(使用Status.values()获取所有可能的值)。

答案 3 :(得分: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) 的函数