Basierend auf Ihrem Fragenverlauf verwenden Sie JSF 2.x. Hier ist eine gezielte Antwort auf JSF 2.x. In JSF 1.x wären Sie gezwungen, Elementwerte / Beschriftungen in hässlichen SelectItemFällen zu verpacken . Dies wird in JSF 2.x glücklicherweise nicht mehr benötigt.
Grundlegendes Beispiel
Um Ihre Frage direkt zu beantworten, verwenden Sie einfach <f:selectItems>deren valuePunkte für eine List<T>Eigenschaft, die Sie während der (Post-) Konstruktion von Bean aus der DB beibehalten. Hier ist ein grundlegendes Kickoff-Beispiel unter der Annahme, dass es sich Ttatsächlich um a handelt String.
<h:selectOneMenu value="#{bean.name}">
<f:selectItems value="#{bean.names}" />
</h:selectOneMenu>
mit
@ManagedBean
@RequestScoped
public class Bean {
private String name;
private List<String> names;
@EJB
private NameService nameService;
@PostConstruct
public void init() {
names = nameService.list();
}
}
So einfach ist das. Tatsächlich werden die T's toString()verwendet, um sowohl die Dropdown-Elementbezeichnung als auch den Wert darzustellen. Wenn Sie also List<String>keine Liste komplexer Objekte wie verwenden List<SomeEntity>und die toString()Methode der Klasse nicht überschrieben haben , werden sie com.example.SomeEntity@hashcodeals Elementwerte angezeigt. Siehe nächster Abschnitt, wie man es richtig löst.
Beachten Sie auch, dass die Bean für den <f:selectItems>Wert nicht unbedingt dieselbe Bean sein muss wie die Bean für den <h:selectOneMenu>Wert. Dies ist immer dann nützlich, wenn es sich bei den Werten tatsächlich um anwendungsweite Konstanten handelt, die Sie beim Start der Anwendung nur einmal laden müssen. Sie können es dann einfach zu einer Eigenschaft einer Bean mit Anwendungsbereich machen.
<h:selectOneMenu value="#{bean.name}">
<f:selectItems value="#{data.names}" />
</h:selectOneMenu>
Komplexe Objekte als verfügbare Elemente
Wenn es sich Tum ein komplexes Objekt (eine Javabean) handelt, das beispielsweise Userdie StringEigenschaft hat name, können Sie das varAttribut verwenden, um die Iterationsvariable abzurufen, die Sie wiederum in itemValueund / oder itemLabelattribtues verwenden können (wenn Sie die weglassen itemLabel, dann die label wird gleich dem Wert).
Beispiel 1:
<h:selectOneMenu value="#{bean.userName}">
<f:selectItems value="#{bean.users}" var="user" itemValue="#{user.name}" />
</h:selectOneMenu>
mit
private String userName;
private List<User> users;
@EJB
private UserService userService;
@PostConstruct
public void init() {
users = userService.list();
}
Oder wenn es eine LongEigenschaft hat, iddie Sie lieber als Elementwert festlegen möchten:
Beispiel 2:
<h:selectOneMenu value="#{bean.userId}">
<f:selectItems value="#{bean.users}" var="user" itemValue="#{user.id}" itemLabel="#{user.name}" />
</h:selectOneMenu>
mit
private Long userId;
private List<User> users;
Komplexes Objekt als ausgewähltes Element
Wann immer Sie es auch auf eine TEigenschaft in der Bean setzen möchten und Teine darstellen Usermöchten, müssen Sie einen benutzerdefinierten ConverterWert backen , der zwischen Usereiner eindeutigen Zeichenfolgendarstellung konvertiert (die die idEigenschaft sein kann). Beachten Sie, dass das itemValuemuss das komplexe Objekt selbst darstellen, genau den Typ, der als Auswahlkomponente festgelegt werden muss value.
<h:selectOneMenu value="#{bean.user}" converter="#{userConverter}">
<f:selectItems value="#{bean.users}" var="user" itemValue="#{user}" itemLabel="#{user.name}" />
</h:selectOneMenu>
mit
private User user;
private List<User> users;
und
@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);
}
}
}
(Bitte beachten Sie, dass das Converteretwas hackig ist, um einen @EJBin einen JSF-Konverter einspeisen zu können ; normalerweise hätte man es als kommentiert @FacesConverter(forClass=User.class), aber das erlaubt leider keine @EJBEinspritzungen )
Vergessen Sie nicht , um sicher zu stellen , dass die komplexe Objektklasse hat equals()und hashCode()ordnungsgemäß umgesetzt werden , sonst JSF wird während machen nicht vorher ausgewählte Artikel zeigen (s), und Sie werden auf Gesicht einreichen Validierungsfehler: Wert nicht gültig ist .
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();
}
}
Komplexe Objekte mit einem generischen Konverter
Gehen Sie zu dieser Antwort: Implementieren Sie Konverter für Entitäten mit Java Generics .
Komplexe Objekte ohne benutzerdefinierten Konverter
Die JSF-Dienstprogrammbibliothek OmniFaces bietet einen speziellen Konverter, mit dem Sie komplexe Objekte verwenden können, <h:selectOneMenu>ohne einen benutzerdefinierten Konverter erstellen zu müssen. Der SelectItemsConverterwird einfach die Konvertierung basierend auf leicht verfügbaren Artikeln in durchführen <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>
Siehe auch: