F: selectItem (s) 'de enum değerleri nasıl kullanılır?


103

Sorumla ilgili bir durum seçebilmek için selectOneMenu açılır menüsü oluşturmak istiyorum. Numaralandırmaların sırası değişirse ve liste büyükse ne olacağını göz önünde bulundurarak f: selectItem'i daha esnek hale getirmek mümkün müdür? Ve bunu daha iyi yapabilir miyim? Ve sorunun sahip olduğu öğeyi otomatik olarak "seçmek" mümkün müdür?

Enum sınıfı

public enum Status {
    SUBMITTED,
    REJECTED,
    APPROVED
}

Soru varlığı

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

Yanıtlar:


210

JSF'nin için yerleşik bir dönüştürücü vardır enum, bu nedenle bu şunları yapmalıdır:

@ManagedBean
@ApplicationScoped
public class Data {

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

}

ile

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

(not: JSF 2.0'dan beri artık a SelectItem[]veya List<SelectItem>, a sağlamaya gerek yoktur T[]ve List<T>kabul edilir ve mevcut öğeye varözniteliğe göre erişebilirsiniz )

JSF yardımcı program kitaplığı OmniFaces kullanıyorsanız , o zaman <o:importConstants>fasulye yerine kullanabilirsiniz .

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

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

Etiketleri de kontrol etmeyi düşünüyorsanız, bunları Statusnumaralandırmaya ekleyebilirsiniz :

public enum Status {

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

    private String label;

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

    public String getLabel() {
        return label;
    }

}

ile

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

Veya daha iyisi, sıralama değerini yerelleştirilmiş bir kaynak paketinin özellik anahtarı yapın (EL 3.0 gereklidir):

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

bununla birlikte kaynak paketiyle ilişkili bir özellikler dosyasında #{text}

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

Bir şey BalusC, bir sorunun varsayılan olarak sahip olduğu durumu "seçmek" / görüntülemek mümkündür (örneğin, bir soruyu düzenlerken, sorunun durumunu zaten bir şeye ayarlamışsınızdır)
LuckyLuke

Yukarıdaki örnekte, JSF #{bean.question.status}geçerli bir enum değerine sahip olduğunda bunu varsayılan olarak yapacaktır . questionUygun status özelliğinin önceden doldurulduğundan emin olmak için herhangi bir şey yapmanız gerekmez .
BalusC

@BalusC JSF'den sıra değerine nasıl erişilir?
jacktrades

2
Benim gibi, bir sayı biçimi istisnası alırsanız, @Ziletka'nın önerdiği gibi += statuskullanmayı deneyin .concat(status).
whistling_marmot

Java.util.List'i tercih ederseniz, getStatuses () 'ı değiştirip türü List <Status>' a döndürebilir ve Arrays.asList (Status.values ​​());
stakahop

16

Yerelleştirme için şu çözümü de kullanabiliriz:

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>

Bu nedenle, yerelleştirme dizeleri için kaynak yolu Enum'da sabit kodlanmaz.


1
Bu sözdiziminin yalnızca "nispeten" yeni olan EL 2.2'den beri desteklendiğine dikkat edin. Aksi takdirde her zaman yakalayabilir <c:set>veya <ui:param>veya özel bir EL işlevi homebrewleri.
BalusC

Teşekkürler BalusC. Destek fasulyesi kullanmadan # {data.statuses} 'ı enum Class ile değiştirmek mümkün müdür (örn. Value = "# {org.myproject.Status.values}")?
sasynkamil

@BalusC emin misin? GF 3.1.2 (Mojarra JSF 2.1.6) kullanıyorum.
sasynkamil

4

Numaralamayı saran örneklerin <f:selectItems value="#{carBean.carList}" />bir listesini kullanabilir ve döndürebilirsiniz SelectItem( Status.values()tüm olası değerleri almak için kullanın ).


2

Enum değerlerini elde etmek ve bunları SelectOneMenuörneğin bir örnekte kullanmak için aşağıdaki yardımcı program işlevini kullanabilirsiniz . Fasulye ve standart yöntemler oluşturmaya gerek yok.

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

Bunu bir taglib dosyasında bir el işlevi olarak kaydedin:

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

Ve sonunda şöyle diyelim:

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

BalusC cevabına benzer şekilde, yerelleştirilmiş enum etiketleri olan bir kaynak paketi kullanmalısınız ve daha temiz bir kod için, aşağıdaki gibi bir işlev de oluşturabilirsiniz: getEnumLabel(enum)


Bir "işleve" (yöntem daha fazla) gerek yok #{myBundle[enumName.i18nKey]}, i18n anahtarlarını özellik olarak kullanıp numaralandırmanıza koyduğunuzda: BLA_TYPE("SOME_BLA_TYPE_KEY")by BLA_TYPEkullanılacak SOME_BLA_TYPE_KEYenumdur ve i18n anahtarıdır.
Roland
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.