如何在f中使用枚举值:selectItem(s)
我想做一个selectOneMenu下拉菜单,这样我就可以在我的问题上select一个状态。 是否有可能使f:selectItem更灵活考虑如果枚举的顺序改变,如果列表很大,会发生什么? 我能做得更好吗? 是否有可能自动“select”该问题的项目?
枚举类
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 ,那么可以使用<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
对于本地化我们可以使用这个解决scheme:
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>
所以本地化string的资源path在Enum中不是硬编码的。
您可以使用<f:selectItems value="#{carBean.carList}" />
并返回一个SelectItem
实例的列表,这些实例包含枚举(使用Status.values()
来获取所有可能的值)。
您可以使用下面的实用程序el函数来获取枚举值,并在SelectOneMenu
使用它们。 不需要创buildbean和样板方法。
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的答案,你应该使用本地化的枚举标签的资源包,并为更干净的代码,你也可以创build一个函数,如getEnumLabel(enum)