使用OmniFaces SelectItemsConverter在HtmlSelectOneMenu中动态预选项目

时间:2014-04-08 11:39:19

标签: jsf jsf-2.2 selectonemenu omnifaces

我想动态创建一个包含所有可能选项的下拉列表(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,我将toString()的{​​{1}}方法更改为:

Category

表单生成的代码如下所示(注意:@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; } ,则会预先选择错误的项目。但是如果我删除它,那么选择了正确的项目,但是当我尝试保存表单时它会失败,因为它没有用于下拉列表的转换器。

任何人都可以帮助我吗?我发布了code on GitHub。 方法menu.setConverter(new SelectItemsConverter());可以在链接代码的底部找到。

2 个答案:

答案 0 :(得分:2)

你的错误在于String.class类型参数:

ValueExpression valueExpression = JSFUtils.createValueExpression(jsfValue, String.class);

Category不是String。请改用Category.class,一切都应该很好。至少在理论上。我无法复制'n'paste'n'run这段代码而不做任何修改。

答案 1 :(得分:1)

我在代码中发现了错误。简单地说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;
}