我想制作一个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>
答案 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)
的函数