webentwicklung-frage-antwort-db.com.de

So verwenden Sie Enum-Werte in f: selectItem (s)

Ich möchte ein selectOneMenu-Dropdown erstellen, damit ich einen Status für meine Frage auswählen kann. Ist es möglich, das f: selectItem flexibler zu gestalten, wenn berücksichtigt wird, was passiert, wenn sich die Reihenfolge der Aufzählungen ändert und die Liste groß ist? Und könnte ich das besser machen? Und ist es möglich, den Gegenstand, den die Frage hat, automatisch "auszuwählen"?

Aufzählungsklasse

public enum Status {
    SUBMITTED,
    REJECTED,
    APPROVED
}

Fragenentität

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

JSF hat einen eingebauten Konverter für enum.

@ManagedBean
@ApplicationScoped
public class Data {

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

}

mit

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

(Anmerkung: Seit JSF 2.0 ist es nicht mehr erforderlich, einen SelectItem[] oder List<SelectItem>, einen T[] und einen List<T> anzugeben. werden ebenfalls akzeptiert und Sie können über das var -Attribut auf den aktuellen Artikel zugreifen.)

Wenn Sie zufällig die JSF-Dienstprogrammbibliothek OmniFaces verwenden, können Sie <o:importConstants> anstelle einer Bean verwenden.

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

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

Wenn Sie beabsichtigen, auch die Beschriftungen zu steuern, können Sie sie der Status -Aufzählung hinzufügen:

public enum Status {

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

    private String label;

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

    public String getLabel() {
        return label;
    }

}

mit

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

Oder machen Sie den Enum-Wert besser zu einem Eigenschaftsschlüssel eines lokalisierten Ressourcenbündels (EL 3.0 erforderlich):

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

mit diesem in einer Eigenschaftendatei, die dem Ressourcenbündel #{text} zugeordnet ist

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

Zur Lokalisierung können wir auch diese Lösung verwenden:

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>

Daher ist der Ressourcenpfad für Lokalisierungszeichenfolgen in Enum nicht fest codiert.

16
Ziletka

Sie können <f:selectItems value="#{carBean.carList}" /> Verwenden und eine Liste von SelectItem Instanzen zurückgeben, die die Aufzählung umschließen (verwenden Sie Status.values(), um alle möglichen Werte abzurufen).

4
Thomas

Sie können das folgende Dienstprogramm el verwenden, um die Aufzählungswerte abzurufen und sie beispielsweise in einem SelectOneMenu zu verwenden. Keine Notwendigkeit, Bohnen und Boilerplate-Methoden zu erstellen.

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

Registrieren Sie es als el-Funktion in einer TagLib-Datei:

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

Und zum Schluss nenne es so:

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

Ähnlich wie bei der BalusC-Antwort sollten Sie ein Ressourcenpaket mit lokalisierten Aufzählungsbezeichnungen verwenden und für saubereren Code können Sie auch eine Funktion wie getEnumLabel(enum) erstellen

2
djmj