2011-11-22 47 views
83

Quiero hacer un menú desplegable de seleccionar un menú para que pueda 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?Cómo usar los valores enum en f: selectItem (s)

Enum clase

public enum Status { 
    SUBMITTED, 
    REJECTED, 
    APPROVED 
} 

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

Respuesta

172

JSF tiene un convertidor incorporado para enum, por lo que este debe 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: ya JSF 2.0 no hay necesidad de más para proporcionar una SelectItem[] o List<SelectItem>, También se aceptan T[] y List<T> y puede acceder al elemento actual por el atributo var)

Si utiliza la biblioteca de utilidades JSF OmniFaces, puede usar <o:importConstants> en 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, así, se podría añadir a la Status enumeración:

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, hacer que el valor de enumeración de 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 asociadas con el paquete de recursos #{text}

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

Una cosa, BalusC, es posible "seleccionar"/ver el estado que una pregunta tiene por defecto (por ejemplo, cuando está editando una pregunta, entonces ya ha establecido el estado de la pregunta a algo) – LuckyLuke

+0

En el ejemplo anterior , JSF lo hará por defecto cuando '# {bean.question.status}' tenga un valor enum válido. No necesita hacer nada para asegurarse de que la 'pregunta' tenga la propiedad de estado correcta previamente cumplimentada. – BalusC

+0

Oh, okey. ¡Lo tengo! :) – LuckyLuke

3

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

14

Para la localización podemos utilizar también 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> 

Así que la ruta del recurso para las cadenas de localización no están codificados en ENUM.

+1

Tenga en cuenta que esta sintaxis solo se admite desde EL 2.2, que es "relativamente" nuevo. De lo contrario, siempre puede tomar '' o '' o homebrew una función EL personalizada. – BalusC

+0

Gracias BalusC. ¿Es posible de alguna manera reemplazar # {data.statuses} con clase enum, sin usar el bean de respaldo (por ejemplo, value = "# {org.myproject.Status.values}")? – Ziletka

+0

@BalusC ¿estás seguro? Estoy usando GF 3.1.2 (Mojarra JSF 2.1.6). – Ziletka

1

Puede usar la siguiente función ell de utilidad para obtener los valores enum y usarlos en un 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; 
    } 
} 

verlo como una función de 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, por último llamar así:

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

Imagen similar a BalusC responder usted debe utilizar un paquete de recursos con etiquetas enum localizadas y para código más limpio también puede crear una función como getEnumLabel(enum)

+0

No necesita una "función" (método más), cuando puede usar '# {myBundle [nombreenum.i18nKey]}' y luego colocar las claves i18n en su enumeración como propiedades: 'BLA_TYPE (" SOME_BLA_TYPE_KEY ")' by 'BLA_TYPE' es la enumeración que se utilizará y' SOME_BLA_TYPE_KEY' es la clave i18n. – Roland

Cuestiones relacionadas