JSF:如何绑定许多h:selectBooleanCheckbox?

时间:2010-10-26 06:54:13

标签: jsf binding checkbox

我有一个问题是将h:selectBooleanCheckbox的列表绑定到我的bean。 有人帮忙吗?

这不起作用:

<ui:repeat value="#{cartBean.productsList}" var="cartProduct" varStatus="i">
   <h:selectBooleanCheckbox binding="#{cartBean.checkboxes[i.index]}" />
</ui:repeat>

public class CartBean extends BaseBean {
  public List<Product> getProductsList() {...}

  private HtmlSelectBooleanCheckbox[] checkboxes;
  public HtmlSelectBooleanCheckbox[] getCheckboxes() {
    return checkboxes;
  }
  public void setCheckboxes(HtmlSelectBooleanCheckbox[] checkboxes) {
    this.checkboxes = checkboxes;
  }
}

我收到错误:

javax.faces.FacesException: javax.el.PropertyNotFoundException: /WEB-INF/flows/main/cart.xhtml @26,97 binding="#{cartBean.checkboxes[i.index]}": Target Unreachable, 'checkboxes' returned null

我解决了我的问题。我使用下面的代码并得到我想要的东西(感谢BalusC博客 - http://balusc.blogspot.com/2006/06/using-datatables.html#SelectMultipleRows):

<ui:repeat value="#{cartBean.productsList}" var="cartProduct" varStatus="i">
  <h:selectBooleanCheckbox value="#{cartBean.selectedIds[cartProduct.id]}" />
</ui:repeat>

public class CartBean extends BaseBean {
  private Map<Integer, Boolean> selectedIds = new HashMap<Integer, Boolean>();
  public Map<Integer, Boolean> getSelectedIds() {
    return selectedIds;
  }
}

2 个答案:

答案 0 :(得分:2)

导致您的具体问题是因为在视图构建期间评估binding属性,即XHTML源代码转换为JSF UI组件树的那一刻,而<ui:repeat>在视图渲染期间运行时间,JSF UI组件树需要生成HTML的那一刻。

换句话说,#{i.index}仅在视图渲染时可用,在视图构建期间评估为null。实际上,你正在进行binding="#{cartBean.checkboxes[null]}"

这里存在另一个概念错误:您似乎期望<ui:repeat>生成多个<h:selectBooleanCheckbox>个物理组件。这是不真实的。物理只有一个 <h:selectBooleanCheckbox>可以多次重复使用,以根据当前迭代的变量生成HTML。实际上,binding="#{cartBean.checkbox}"已经足够了。然而,收集价值观是一个独特的故事。我不会详细介绍,但你可以在这个答案中找到几个提示:Validate order of items inside ui:repeat

为了实现(明显的)生成物理多个<h:selectBooleanCheckbox>组件并将每个组件绑定到单独的数组项的具体功能要求,您应该使用在视图构建时运行而不是视图呈现的迭代组件时间。这是JSTL <c:forEach>

<c:forEach items="#{cartBean.productsList}" var="cartProduct" varStatus="i">
    <h:selectBooleanCheckbox binding="#{cartBean.checkboxes[i.index]}" />
</c:forEach>

但是,毕竟应尽可能避免在bean属性上使用binding。请准确使用您最终需要的属性:value属性。这样您每次都不需要HtmlSelectBooleanCheckbox#getValue()。您已经使用Map<Integer, Boolean> selectedIds

找到了正确的解决方案
<ui:repeat value="#{cartBean.productsList}" var="cartProduct">
    <h:selectBooleanCheckbox value="#{cartBean.selectedIds[cartProduct.id]}" />
</ui:repeat>

另见:

答案 1 :(得分:0)

我不知道你是否可以绑定存储在数组中的元素。但在您的代码中,问题是您的HtmlSelectBooleanCheckbox[]null。所以也许可以将Java代码更改为:

public HtmlSelectBooleanCheckbox[] getCheckboxes() {
    if (checkboxes == null) {
        checkboxes = new HtmlSelectBooleanCheckbox[getProductsList().size()];
    }
    return checkboxes;
}

但我真的不确定它是否可行......也许解决方案是不绑定Java代码中的HtmlSelectBooleanCheckbox元素。你为什么需要绑定它们?