<h:selectOneMenu>
或<p:selectOneMenu>
是否需要使用任意用户创建的类作为其值?我的意思是,以下代码应该在没有转换器的情况下工作吗?
<p:selectOneMenu value="#{bean.language}">
<f:selectItems value="#{bean.allLanguages}" />
</p:selectOneMenu>
和
@Named(value = "bean")
@ConversationScoped
public class Bean {
private Language language; // appropriate getter and setter are present
public List<SelectItem> getAllLanguages() {
// populates a list of select items with Strings as item labels and Languages as item values
}
}
我有一个类似的代码,enum
作为类型(语言),它完美无缺。但是当我用普通的java类替换类型时,我得到转换错误。
答案 0 :(得分:1)
这里需要一个转换器,因为JSF默认采用字符串,这就是你编码的方式。 JSF不知道如何将伪实体转换为字符串,反之亦然。
一些注意事项:
1。您的getAsString
方法定义了您的实体/ POJO的标识符,而不是JSF(或其他)选择作为itemLabel的标识符。
2。您的转换器可以使用这篇臭名昭着的文章挖掘真实实体的数据库:
您也可以使用带有“模式”的CDI注释。
3。您的value = "bean"
是多余的,CDI的选择范围通常是@ViewScoped
。但是,您必须记住,如果不使用Seam 3或Apache MyFaces CODI,CDI @Named
+ JSF @ViewScoped
不能协同工作。
答案 1 :(得分:1)
你不需要转换器,如果你使用我写的这个小类:-)它可以返回selectOne和selecteMany组件。它要求您的类的toString()提供对象的一对一唯一表示。如果您愿意,可以替换toString()以外的方法名称,例如toIDString()
要在ManagedBean中使用ListBacker,请在使用ListBacker<Type>
List<Type>
@ManagedBean
@RequestScoped
public class BackingBean {
private ListBacker<User> users; // +getter +setter
@PostConstruct
public void init() {
// fill it up from your DAO
users = new ListBacker<User>(userDAO.find());
}
// Here's the payoff! When you want to use the selected object,
// it is just available to you, with no extra database hits:
User thisOneIsSelected = users.getSelectedItemAsObject();
// or for multi-select components:
List<User> theseAreSelected = users.getSelectedItemsAsObjects();
}
在你的xhtml文件中:
<p:selectOneMenu value="#{backingBean.users.selectedItem}">
<f:selectItems value="#{backingBean.users.contents}" var="item" itemValue="#{item.value}" itemLabel="#{item.label}" />
</p:selectOneMenu>
ListBacker类:
public class ListBacker<T extends AbstractEntityBase> {
// Contains the String representation of an Entity's ID (a.k.a.
// primary key) and the associated Entity object
Map<String, T> contents = new LinkedHashMap<String, T>(); // LinkedHashMap defaults to insertion-order iteration.
// These hold values (IDs), not labels (descriptions).
String selectedItem; // for SelectOne list
List<String> selectedItems; // for SelectMany list
public class ListItem {
private String value;
private String label;
public ListItem(String value, String label) {
this.value = value;
this.label = label;
}
public String getValue() {
return value;
}
public String getLabel() {
return label;
}
}
public ListBacker() {}
public ListBacker(List<T> lst) {
put(lst);
}
public void clear() {
contents.clear();
selectedItem = null;
if(selectedItems != null) {
selectedItems.clear();
}
}
public List<ListItem> getContents() {
return convert(contents);
}
public String getSelectedItem() {
return selectedItem;
}
public void setSelectedItem(String selectedItem) {
this.selectedItem = selectedItem;
}
public List<String> getSelectedItems() {
return selectedItems;
}
public void setSelectedItems(List<String> selectedItems) {
this.selectedItems = selectedItems;
}
public T getSelectedItemAsObject() {
return convert(selectedItem);
}
public List<T> getSelectedItemsAsObjects() {
return convert(selectedItems);
}
public void put(T newItem) {
contents.put(newItem.toString(), newItem);
}
public void put(List<T> newItems) {
for (T t : newItems) {
put(t);
}
}
// PROTECTED (UTILITY) METHODS
protected List<ListItem> convert(Map<String, T> maps) {
List<ListItem> lst = new ArrayList<ListItem>();
for (Entry<String, T> e : maps.entrySet()) {
lst.add(new ListItem(e.getKey(), e.getValue().desc()));
}
return lst;
}
protected List<T> convert(List<String> ids) {
List<T> lst = new ArrayList<T>();
for (String id : ids) {
lst.add(convert(id));
}
return lst;
}
protected T convert(String id) {
return contents.get(id);
}
}
我有两个toString()实现,一个用于JPA实体:
public abstract class AbstractEntityBase {
@Override
public final String toString() {
return String.format("%s[id=%s]", getClass().getSimpleName(), getIdForToString().toString());
}
/**
* Return the entity's ID, whether it is a field or an embedded ID class..
* @return ID Object
*/
protected abstract Object getIdForToString();
}
和JPA EmbeddedId的一个:
public abstract class CompositeKeyBase {
@Override
public final String toString() {
return String.format("%s[id=%s]", getClass().getSimpleName(), getIdForToString());
}
/**
* Supports the class's toString() method, which is required for ListBacker.
* Compile a string of all ID fields, with this format:
* fieldName=StringVALUE,field2=STRINGvAlUE2,...,fieldx=stringvalue <br />
* Recommended: start with Eclipse's "generate toString()" utility and move it to getIdForToString()
* @return a 1-to-1 String representation of the composite key
*/
public abstract String getIdForToString();
}
getIdForToString()的示例实现,用于具有一个Id字段的实体:
@Override
public Object getIdForToString() {
return userID;
}
getIdForToString()的示例实现,用于具有两个字段的EmbeddedId:
@Override
public String getIdForToString() {
return "userID=" + userID + ",roleID=" + roleID;
}