2014-04-08 56 views
1

我想動態創建包含所有可能選項的下拉列表(HtmlSelectOneMenu)。當前設置的選項應該被預先選擇。要做到這一點,我創建了自己的狀態值表達式:使用OmniFaces SelectItemsConverter動態預選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我改變了CategorytoString()方法:

@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());,則預選了錯誤的項目。但是,如果我刪除它,然後選擇正確的項目,但當我嘗試保存表單失敗,因爲它沒有下拉轉換器。

任何人都可以幫助我嗎?我已經發布了code on GitHub。 方法createDropdown可以在鏈接代碼的底部找到。

回答

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; 
} 
2

你的錯誤是在這裏,在String.class類型參數:

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

一個Category不是String。改用Category.class,一切都會好的。至少在理論上。我不能在沒有改變的情況下複製'n'paste'運行這段代碼。

+0

BalusC嗨。謝謝您的回答。我試過了,但沒有奏效。但是我提出了以下意見:在值表達式中使用「Category.class」時,選擇框中的每個項目都將被選中(

+0

您應該在提交時收到「驗證錯誤:值無效」,但您沒有提及它。另請參閱http://stackoverflow.com/a/9069660和http://stackoverflow.com/a/17343582 – BalusC

相關問題