jsf jsf-2 enums selectonemenu

jsf - Cómo usar los valores enum en f: selectItem(s)



jsf-2 enums (4)

Quiero hacer un menú desplegable selectOneMenu para poder seleccionar un estado en mi pregunta. ¿Es posible hacer que f: selectItem sea más flexible teniendo en cuenta lo que sucede si el orden de las enumeraciones cambia, y si la lista era grande? ¿Y podría hacerlo mejor? ¿Y es posible "seleccionar" automáticamente el elemento que tiene la pregunta?

Clase Enum

public enum Status { SUBMITTED, REJECTED, APPROVED }

Entidad de pregunta

@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 tiene un convertidor incorporado para enum , así que esto debería hacer:

@ManagedBean @ApplicationScoped public class Data { public Status[] getStatuses() { return Status.values(); } }

con

<h:selectOneMenu value="#{bean.question.status}" > <f:selectItems value="#{data.statuses}" /> </h:selectOneMenu>

(nota: desde JSF 2.0 ya no hay necesidad de proporcionar un SelectItem[] o List<SelectItem> , también se List<SelectItem> T[] y List<T> y se puede acceder al elemento actual mediante el atributo var )

Si usa la biblioteca de utilidades JSF OmniFaces , puede usar <o:importConstants> lugar de un bean.

<o:importConstants type="com.example.Status" /> <h:selectOneMenu value="#{bean.question.status}" > <f:selectItems value="#{Status}" /> </h:selectOneMenu>

Si tiene la intención de controlar las etiquetas también, puede agregarlas a la enumeración de 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; } }

con

<f:selectItems value="#{data.statuses}" var="status" itemValue="#{status}" itemLabel="#{status.label}" />

O mejor, haga que el valor enum sea una clave de propiedad de un paquete de recursos localizado (se requiere EL 3.0):

<f:selectItems value="#{data.statuses}" var="status" itemValue="#{status}" itemLabel="#{text[''data.status.'' += status]}" />

con esto en un archivo de propiedades asociado con el paquete de recursos #{text}

data.status.SUBMITTED = Submitted data.status.REJECTED = Rejected data.status.APPROVED = Approved


Para la localización también podemos usar esta solución:

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>

Por lo tanto, la ruta del recurso para las cadenas de localización no está codificada en Enum.


Puede usar <f:selectItems value="#{carBean.carList}" /> y devolver una lista de instancias de SelectItem que envuelven la enumeración (use Status.values() para obtener todos los valores posibles).


Puede usar la siguiente función de utilidad para obtener los valores enum y usarlos en SelectOneMenu por ejemplo. No es necesario crear frijoles y métodos repetitivos.

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; } }

Regístrelo como una función el en un archivo taglib:

<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>

Y finalmente llámalo así:

<p:selectOneMenu value="#{bean.type}"> <f:selectItems value="#{el:getEnumValues(''package.BeanType'')}" var="varEnum" itemLabel="#{el:getEnumLabel(varEnum)}" itemValue="#{varEnum}"/> </p:selectOneMenu>

De forma similar a la respuesta de BalusC, debe utilizar un paquete de recursos con etiquetas enum localizadas y, para obtener un código más limpio, también puede crear una función como getEnumLabel(enum)