我想动态创建一个包含所有可能选项的下拉列表(HtmlSelectOneMenu)。应预先选择当前设置的选项。为了实现这一点,我为我的表单创建了一个值表达式:
String jsfValue = String.format("#{%s.item.%s}", getControllerBeanName(), key);
ValueExpression valueExpression = JSFUtils.createValueExpression(jsfValue, String.class);
menu.setValueExpression("value", valueExpression);
字符串#{%s.item.%s}
的计算结果为#{playlistController.item.category}
,而category
是我要绑定到下拉列表的类型为Category
的对象。
为了使用OmniFaces的SelectItemsConverter
,我将Category
的toString()
方法更改为:
@Override
public String toString() {
return String.format("%s[id=%d]", getClass().getSimpleName(), getId());
}
我的表单生成代码如下(注意:Category
扩展了BaseEntity
):
private UIComponent createDropdown(FormInput property) {
String key = property.getKey();
String beanName = key + "Controller";
GenFormBaseController controller = (GenFormBaseController) JSFUtils.getManagedBean(beanName);
List<BaseEntity> list = controller.getService().findAll();
List<SelectItem> selectItems = new ArrayList<>(list.size());
for (BaseEntity itemInList : list) {
selectItems.add(new SelectItem(itemInList, itemInList.getName()));
}
UISelectItems items = new UISelectItems();
items.setValue(selectItems.toArray());
HtmlSelectOneMenu menu = new HtmlSelectOneMenu();
menu.setConverter(new SelectItemsConverter());
menu.setId(key);
menu.getChildren().add(items);
String jsfValue = String.format("#{%s.item.%s}", getControllerBeanName(), key);
ValueExpression valueExpression = JSFUtils.createValueExpression(jsfValue, String.class);
menu.setValueExpression("value", valueExpression);
return menu;
}
如果我设置了menu.setConverter(new SelectItemsConverter());
,则预选了错误的项目。但是,如果我删除它,那么会选择正确的项目,但当我尝试保存表单时,它失败了,因为它没有下拉列表的转换器。
有人能帮我吗?我已经在GitHub上发布了代码。方法createDropdown
可以在链接代码的底部找到。
您的错误就在这里,在String.class
类型参数中:
ValueExpression valueExpression = JSFUtils.createValueExpression(jsfValue, String.class);
Category
不是String
。改用Category.class
,一切都会好起来。至少在理论上是这样。如果不进行更改,我就无法复制、粘贴或运行这段代码。
我在代码中发现了错误。简单地说,BaseEntity的equals()和hashCode()是不够的。以及BalusC已经提到的错误。生成的代码如下所示:
GenFormBaseController.java
private UIComponent createDropdown(FormInput property) {
String key = property.getKey();
Class<?> expectedType = property.getValue();
String beanName = lowerFirstChar(expectedType.getSimpleName()) + "Controller";
GenFormBaseController controller = (GenFormBaseController) JSFUtils.getManagedBean(beanName);
List<BaseEntity> list = controller.getService().findAll();
List<SelectItem> selectItems = new ArrayList<>(list.size());
for (BaseEntity itemInList : list) {
selectItems.add(new SelectItem(itemInList, itemInList.getName()));
}
UISelectItems items = new UISelectItems();
items.setValue(selectItems);
HtmlSelectOneMenu menu = new HtmlSelectOneMenu();
menu.setConverter(new SelectItemsConverter());
menu.setId(key);
menu.getChildren().add(items);
String jsfValue = String.format("#{%s.item.%s}", getControllerBeanName(), key);
ValueExpression valueExpression = JSFUtils.createValueExpression(jsfValue, expectedType);
menu.setValueExpression("value", valueExpression);
return menu;
}
BaseEntity.java
@Override
public int hashCode() {
int hash = 7;
hash = 97 * hash + Objects.hashCode(this.id);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final BaseEntity other = (BaseEntity) obj;
if (!Objects.equals(this.id, other.id)) {
return false;
}
return true;
}