Je souhaite créer un menu déroulant selectOneMenu afin de pouvoir sélectionner un statut pour ma question. Est-il possible de rendre le f: selectItem plus flexible en considérant ce qui se passe si l'ordre des enums change, et si la liste était longue? Et pourrais-je faire cela mieux? Et est-il possible de "sélectionner" automatiquement l'élément que la question contient?
Enum class
public enum Status {
SUBMITTED,
REJECTED,
APPROVED
}
entité Question
@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 a un convertisseur intégré pour enum
, cela devrait donc:
@ManagedBean
@ApplicationScoped
public class Data {
public Status[] getStatuses() {
return Status.values();
}
}
avec
<h:selectOneMenu value="#{bean.question.status}" >
<f:selectItems value="#{data.statuses}" />
</h:selectOneMenu>
(remarque: depuis JSF 2.0, il n'est plus nécessaire de fournir un SelectItem[]
ou List<SelectItem>
, une T[]
et List<T>
sont également acceptés et vous pouvez accéder à l’élément en cours avec var
attribut)
Si vous utilisez la bibliothèque d’utilitaires JSF OmniFaces , vous pouvez utiliser <o:importConstants>
au lieu d'un haricot.
<o:importConstants type="com.example.Status" />
<h:selectOneMenu value="#{bean.question.status}" >
<f:selectItems value="#{Status}" />
</h:selectOneMenu>
Si vous avez également l'intention de contrôler les étiquettes, vous pouvez les ajouter à l'énumération 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;
}
}
avec
<f:selectItems value="#{data.statuses}" var="status"
itemValue="#{status}" itemLabel="#{status.label}" />
Ou mieux, faites de la valeur enum une clé de propriété d'un regroupement de ressources localisées (EL 3.0 requise):
<f:selectItems value="#{data.statuses}" var="status"
itemValue="#{status}" itemLabel="#{text['data.status.' += status]}" />
avec cela dans un fichier de propriétés associé au groupe de ressources #{text}
data.status.SUBMITTED = Submitted
data.status.REJECTED = Rejected
data.status.APPROVED = Approved
Pour la localisation, nous pouvons également utiliser cette solution:
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>
Ainsi, le chemin d'accès aux ressources pour les chaînes de localisation n'est pas codé en dur dans Enum.
Vous pouvez utiliser <f:selectItems value="#{carBean.carList}" />
Et renvoyer une liste d'instances SelectItem
qui encapsulent l'énumération (utilisez Status.values()
pour obtenir toutes les valeurs possibles).
Vous pouvez utiliser l'utilitaire el suivant pour obtenir les valeurs enum et les utiliser dans un SelectOneMenu
par exemple. Pas besoin de créer des haricots et des méthodes passe-partout.
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;
}
}
Enregistrez-le en tant que fonction el dans un fichier 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>
Et enfin, appelez ça comme:
<p:selectOneMenu value="#{bean.type}">
<f:selectItems value="#{el:getEnumValues('package.BeanType')}" var="varEnum"
itemLabel="#{el:getEnumLabel(varEnum)}" itemValue="#{varEnum}"/>
</p:selectOneMenu>
Comme pour la réponse BalusC, vous devriez utiliser un ensemble de ressources avec des étiquettes d'énum localisées. Pour un code plus propre, vous pouvez également créer une fonction comme getEnumLabel(enum)