D'après l'historique de vos questions, vous utilisez JSF 2.x. Voici donc une réponse adaptée à JSF 2.x. Dans JSF 1.x, vous seriez contraint d'envelopper les valeurs/étiquettes des éléments dans d'affreux fichiers SelectItem
instances. Heureusement, cela n'est plus nécessaire dans JSF 2.x.
Exemple de base
Pour répondre directement à votre question, il suffit d'utiliser <f:selectItems>
dont value
pointe vers un List<T>
propriété que vous préservez de la DB pendant la (post)construction du haricot. Voici un exemple de démarrage de base en supposant que T
représente en fait un String
.
<h:selectOneMenu value="#{bean.name}">
<f:selectItems value="#{bean.names}" />
</h:selectOneMenu>
avec
@ManagedBean
@RequestScoped
public class Bean {
private String name;
private List<String> names;
@EJB
private NameService nameService;
@PostConstruct
public void init() {
names = nameService.list();
}
// ... (getters, setters, etc)
}
C'est aussi simple que cela. En fait, le T
's toString()
sera utilisé pour représenter à la fois le libellé et la valeur de l'élément de la liste déroulante. Ainsi, lorsque vous êtes au lieu de List<String>
en utilisant une liste d'objets complexes comme List<SomeEntity>
et que vous n'avez pas surchargé la classe toString()
vous verrez alors com.example.SomeEntity@hashcode
comme valeurs d'éléments. Voir la section suivante pour savoir comment le résoudre correctement.
Notez également que le haricot pour <f:selectItems>
ne doit pas nécessairement être le même bean que le bean pour <h:selectOneMenu>
valeur. Ceci est utile lorsque les valeurs sont en fait des constantes de l'application que vous n'avez à charger qu'une seule fois pendant le démarrage de l'application. Vous pouvez alors simplement en faire une propriété d'un bean à portée applicative.
<h:selectOneMenu value="#{bean.name}">
<f:selectItems value="#{data.names}" />
</h:selectOneMenu>
Objets complexes comme éléments disponibles
Chaque fois que T
concerne un objet complexe (un javabean), tel que User
qui a un String
propriété de name
alors vous pouvez utiliser l'option var
pour obtenir la variable d'itération que vous pouvez utiliser à votre tour dans itemValue
et/ou itemLabel
attributs (si vous omettez le itemLabel
alors l'étiquette devient la même que la valeur).
Exemple n° 1 :
<h:selectOneMenu value="#{bean.userName}">
<f:selectItems value="#{bean.users}" var="user" itemValue="#{user.name}" />
</h:selectOneMenu>
avec
private String userName;
private List<User> users;
@EJB
private UserService userService;
@PostConstruct
public void init() {
users = userService.list();
}
// ... (getters, setters, etc)
Ou quand il a un Long
propriété id
que vous souhaitez plutôt définir comme valeur d'élément :
Exemple n° 2 :
<h:selectOneMenu value="#{bean.userId}">
<f:selectItems value="#{bean.users}" var="user" itemValue="#{user.id}" itemLabel="#{user.name}" />
</h:selectOneMenu>
avec
private Long userId;
private List<User> users;
// ... (the same as in previous bean example)
Objet complexe comme élément sélectionné
Chaque fois que vous voulez le mettre sur un T
dans le haricot ainsi que T
représente un User
vous devez alors créer un fichier personnalisé Converter
qui convertit entre User
et une représentation unique sous forme de chaîne de caractères (qui peut être l' id
propriété). Veuillez noter que le itemValue
doit représenter l'objet complexe lui-même, exactement le type qui doit être défini en tant qu'élément de sélection du composant value
.
<h:selectOneMenu value="#{bean.user}" converter="#{userConverter}">
<f:selectItems value="#{bean.users}" var="user" itemValue="#{user}" itemLabel="#{user.name}" />
</h:selectOneMenu>
avec
private User user;
private List<User> users;
// ... (the same as in previous bean example)
y
@ManagedBean
@RequestScoped
public class UserConverter implements Converter {
@EJB
private UserService userService;
@Override
public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
if (submittedValue == null || submittedValue.isEmpty()) {
return null;
}
try {
return userService.find(Long.valueOf(submittedValue));
} catch (NumberFormatException e) {
throw new ConverterException(new FacesMessage(String.format("%s is not a valid User ID", submittedValue)), e);
}
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object modelValue) {
if (modelValue == null) {
return "";
}
if (modelValue instanceof User) {
return String.valueOf(((User) modelValue).getId());
} else {
throw new ConverterException(new FacesMessage(String.format("%s is not a valid User", modelValue)), e);
}
}
}
(veuillez noter que le Converter
est un peu bricolé pour pouvoir injecter une @EJB
dans un convertisseur JSF ; normalement, on l'aurait annoté en tant que @FacesConverter(forClass=User.class)
, mais cela ne permet malheureusement pas @EJB
injections )
N'oubliez pas de vous assurer que la classe d'objets complexes possède equals()
y hashCode()
correctement mis en œuvre sinon, lors du rendu, JSF n'affichera pas les éléments présélectionnés, et vous serez confronté à l'échec de l'opération. Erreur de validation : La valeur n'est pas valide .
public class User {
private Long id;
@Override
public boolean equals(Object other) {
return (other != null && getClass() == other.getClass() && id != null)
? id.equals(((User) other).id)
: (other == this);
}
@Override
public int hashCode() {
return (id != null)
? (getClass().hashCode() + id.hashCode())
: super.hashCode();
}
}
Objets complexes avec un convertisseur générique
Dirigez-vous vers cette réponse : Implémenter des convertisseurs pour les entités avec Java Generics .
Objets complexes sans convertisseur personnalisé
La bibliothèque utilitaire JSF OmniFaces offre un convertisseur spécial qui vous permet d'utiliser des objets complexes dans les applications de l'UE. <h:selectOneMenu>
sans qu'il soit nécessaire de créer un convertisseur personnalisé. Le site SelectItemsConverter
effectuera simplement la conversion en se basant sur des éléments facilement disponibles dans les pays de l'UE. <f:selectItem(s)>
.
<h:selectOneMenu value="#{bean.user}" converter="omnifaces.SelectItemsConverter">
<f:selectItems value="#{bean.users}" var="user" itemValue="#{user}" itemLabel="#{user.name}" />
</h:selectOneMenu>
Voir aussi :