2011-11-22 10 views
83

Chcę, aby wybrać menu rozwijane selectOneMenu, dzięki czemu mogę wybrać status na moim pytaniu. Czy jest możliwe, aby f: selectItem był bardziej elastyczny, biorąc pod uwagę, co się stanie, jeśli kolejność wyliczeń się zmieni i czy lista będzie duża? Czy mogę zrobić to lepiej? Czy możliwe jest automatyczne "wybranie" elementu, który ma pytanie?Jak używać wartości wyliczeniowych w f: selectItem (s)

Enum klasa

public enum Status { 
    SUBMITTED, 
    REJECTED, 
    APPROVED 
} 

jednostka Pytanie

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

Odpowiedz

172

JSF ma wbudowanego konwertera dla enum, więc powinno to zrobić:

@ManagedBean 
@ApplicationScoped 
public class Data { 

    public Status[] getStatuses() { 
     return Status.values(); 
    } 

} 

z

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

(uwaga: od JSF 2.0 nie ma już potrzeby, aby zapewnić SelectItem[] lub List<SelectItem>, akceptuje się także T[] i List<T>, a dostęp do bieżącego elementu można uzyskać za pomocą atrybutu var)

Jeśli używasz biblioteki narzędziowej JSF OmniFaces, możesz zamiast tego użyć <o:importConstants>.

<o:importConstants type="com.example.Status" /> 

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

Jeśli zamierzają kontrolować etykiety, jak również, można je dodać do Status wyliczenia:

public enum Status { 

    SUBMITTED("Submitted"), 
    REJECTED("Rejected"), 
    APPROVED("Approved"); 

    private String label; 

    private Status(String label) { 
     this.label = label; 
    } 

    public String getLabel() { 
     return label; 
    } 

} 

z

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

lub lepiej zrobić wartość enum A klucz własności zlokalizowanego pakunku zasobów (wymagane EL 3.0):

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

z tym w pliku właściwości związanych z pakunku zasobów #{text}

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

Jedną z rzeczy BalusC, czy możliwe jest "wybranie"/wyświetlenie statusu, który ma domyślne pytanie (na przykład podczas edytowania pytania, to już ustawiłeś status pytania na coś) – LuckyLuke

+0

W powyższym przykładzie , JSF zrobi to domyślnie, gdy '# {bean.question.status}' ma poprawną wartość wyliczenia. Nie musisz robić niczego, czego można się spodziewać, aby upewnić się, że 'pytanie' ma właściwość właściwego stanu wstępnie wypełniona. – BalusC

+0

Oh, okey. Rozumiem! :) – LuckyLuke

3

Można użyć <f:selectItems value="#{carBean.carList}" /> i zwrócić listę instancji SelectItem, które zawijają wyliczenie (użyj Status.values(), aby uzyskać wszystkie możliwe wartości).

14

Dla lokalizacji możemy korzystać również z tego rozwiązania:

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> 

Więc ścieżka zasobu dla ciągów lokalizacyjnych nie są sztywno w Enum.

+1

Należy zauważyć, że ta składnia jest obsługiwana tylko od wersji EL 2.2, która jest "względnie" nowa. W przeciwnym razie zawsze możesz pobrać '' lub '' lub homebrew niestandardową funkcją EL. – BalusC

+0

Dziękuję BalusC. Czy jest możliwe, aby w jakiś sposób zastąpić # {data.statuses} klasą enum, bez użycia komponentu bean (np. Value = "# {org.myproject.Status.values}")? – Ziletka

+0

@BalusC jesteś pewien? Używam GF 3.1.2 (Mojarra JSF 2.1.6). – Ziletka

1

Możesz użyć następującej funkcji el narzędziowej, aby uzyskać wartości wyliczeniowe i na przykład użyć ich w postaci SelectOneMenu. Nie ma potrzeby tworzenia fasoli i metod standardowych.

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

zarejestrować ją jako funkcję el w pliku 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> 

i wreszcie nazwać to lubią:

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

podobne do BalusC odpowiedzieć należy używać pakiet zasobów z lokalnymi etykietami wyliczającymi i czystszym kodem możesz również utworzyć funkcję podobną do: getEnumLabel(enum)

+0

Nie trzeba używać "funkcji" (metoda więcej), kiedy można użyć '# {myBundle [enumName.i18nKey]}', a następnie umieścić klucze i18n w swoim wyliczeniu jako właściwości: 'BLA_TYPE (" SOME_BLA_TYPE_KEY ")' według 'BLA_TYPE' jest wylicznikiem, którego należy użyć, a' SOME_BLA_TYPE_KEY' jest kluczem i18n. – Roland

Powiązane problemy