2012-09-29 19 views
2

我正在使用SelectMany Checkboxes primefaces并在Bean中存储值时遇到一些麻烦。我需要一个SelectManyCheck框数组。这里是目前为止的xhtml,JSF SelectMany复选框,绑定到子列表

<c:set var="obj" value="#{userBean.userSettingsMap}"> </c:set> 
<c:forEach items="#{obj}" var="entry"> 
    <h:outputText value="#{entry.key} " /><!--Correctly prints the key --> 
    <p:selectManyCheckbox value="#{entry.value}"><!-- `entry.value` SHOULD correspond to inner lists ---> 
    <!-- I want values of these check boxes to be updated in my ManagedBean's property --> 
    <f:selectItem itemLabel="Option 1" itemValue="Option 1" /> 
    <f:selectItem itemLabel="Option 2" itemValue="Option 2" /> 
    <f:selectItem itemLabel="Option 3" itemValue="Option 3" /> 
</p:selectManyCheckbox> 
</c:forEach> 

在页面上呈现选择多个复选框的数组。但是当我提交页面时,子列表不会更新。而我的ManagedBean中的对象没有得到更新。

所以,在提交时,我得到了对话框上显示的空白列表。

{密钥1 = [],键2 = []}

以我ManagedBean我有,

private Map<String,List<String>> userSettingsMap; 

当子列表将对应于每个<p:selectManyCheckbox>上视图

提交按钮与示例中的相同。

<p:commandButton value="Submit" update="display" oncomplete="dlg.show()" /> 
    <p:dialog header="Selected Values" modal="true" showEffect="fade" hideEffect="fade" widgetVar="dlg"> 

     <p:outputPanel id="display"> 
      <p:dataList value="#{userService.userMaintainceMap}" var="option"> 
       #{option} 
      </p:dataList>    
     </p:outputPanel> 

回答

3

您遍历使用地图JSTL的c:forEach,这意味着每一项都将是一个内部迭代器类型这是最有可能的Map.Entry(例如MappedValueExpression.Entry)的实现。这里有一个setValue方法,但它不能确认JavaBeans约定,这意味着EL不会找到它。

结果#{entry.value}将被视为一个只读属性<p:selectManyCheckbox>将无法​​保存它的价值在那里。我期望会出现一个异常,但也许它会被吞噬。一个正常的窗体和一个正常的命令按钮肯定会在这里触发一个异常。

第二个问题是你有一个泛型地图作为你选择的目标,但是EL将无法看到那些泛型(指责在Java中泛化的泛型缺乏),因此不会看到该值是一个List。然后它会在您的地图中放置一个String[]实例。

如果您使用您的地图表达式作为您选择的目标,并声明要键入的地图为String[],那么您的代码应该可以工作。

E.g.

innercheckbox.xhtml:

<html xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:f="http://java.sun.com/jsf/core" 
    xmlns:c="http://java.sun.com/jsp/jstl/core" 
    xmlns:p="http://primefaces.org/ui"> 

    <h:body> 

     <h:form> 
      <c:forEach items="#{innerCheckboxBacking.userSettingsMap}" var="entry"> 
       <h:outputText value="#{entry.key}" /> 
       <p:selectManyCheckbox value="#{innerCheckboxBacking.userSettingsMap[entry.key]}"> 
        <f:selectItem itemLabel="Option 1" itemValue="Option 1" /> 
        <f:selectItem itemLabel="Option 2" itemValue="Option 2" /> 
        <f:selectItem itemLabel="Option 3" itemValue="Option 3" /> 
       </p:selectManyCheckbox> 
      </c:forEach> 

      <h:commandButton value="Submit" action="#{innerCheckboxBacking.action}" /> 

     </h:form> 

    </h:body> 
</html> 

InnerCheckboxBacking.java:

@ManagedBean 
@ViewScoped 
public class InnerCheckboxBacking { 

    private Map<String, String[]> userSettingsMap = new LinkedHashMap<>(); 

    @PostConstruct 
    public void init() { 
     userSettingsMap.put("key1", null); 
     userSettingsMap.put("key2", null); 
    } 

    public void action() { 
     String[] result = userSettingsMap.get("key1"); 
     for (String string : result) { 
      System.out.println(string); 
     } 
    } 

    public Map<String, String[]> getUserSettingsMap() { 
     return userSettingsMap; 
    } 

} 
+0

很好的解释@Arjan,我会尝试相应地改变我的代码,然后回来。 thnx。\ –

+1

澄清第二个问题更多:这不是因为'List'是通用的,而是因为'Map'是通用的,因此EL没有看到该值实际上是一个'List'。然而,'UISelectMany'组件本身支持一个'List'作为值(其类型默认为'String',但可以通过显式指定'Converter'来覆盖)。 – BalusC

+0

由两个伟大的人回答和评论! @BalusC thnx清理。我最近一直在关注你的博客。很高兴看到您的评论。我知道我会需要自定义转换器。但是我发现自己对这方面的知识不够。我将探索转换器。 thnx很多:) –