JSF SelectMany复选框,绑定到子列表

时间:2012-09-29 08:07:12

标签: jsf jsf-2 primefaces

我正在使用SelectMany Checkboxes的primefaces,并且在将值存储在Bean中时遇到了一些麻烦。

我需要一组SelectManyCheck框。到目前为止,这是xhtml,

<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中的对象没有得到更新。

因此,在提交时,我会在对话框中显示空白列表。

  

{key 1 = [],key 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>

1 个答案:

答案 0 :(得分:3)

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

因此,#{entry.value}将被视为只读属性,而<p:selectManyCheckbox>将无法在其中存储其值。我希望看到一个例外,但也许它会被某个地方吞噬。普通表单和普通命令按钮肯定会在这里触发异常。

第二个问题是你有一个带有泛型的Map作为你选择的目标,但是EL将无法看到那些泛型(归咎于臭名昭着的Java缺乏统一的泛型),因此将特别看不到value是一个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;
    }

}