【问题标题】:Primefaces ManyCheckbox inside ui:repeat calls setter method only for last loopui中的Primefaces ManyCheckbox:repeat仅针对最后一个循环调用setter方法
【发布时间】:2012-10-20 06:59:12
【问题描述】:

我在<ui:repeat> 中有一个<p:selectManyCheckbox>,从某个对象类的列表中获取它的项目(由<ui:repeat>-variable 提供),并且应该将所选项目保存到同一对象类的另一个列表中.但它只为最后一个条目(<ui:repeat> 的最后一次迭代)调用 setter 方法 #{cartBean.setSelectedExtras}

<ui:repeat var="item" value="#{category.items}">
    <p:selectManyCheckbox id="extraCheckbox" value="#{cartBean.selectedExtras}" layout="pageDirection" converter="omnifaces.SelectItemsConverter">  
         <f:selectItems value="#{item.items5}" var="extra" itemLabel="#{extra.name}"/>
    </p:selectManyCheckbox>
</ui:repeat>

更新: 我按照 BalusC 提议的方式更改了上述构造。
支持 bean 中的声明现在是:

private List<List<Item>>  selectedExtras   = new ArrayList<List<Item>>();

当我选中由&lt;ui:repeat&gt; 的第一个循环创建的复选框并单击同一&lt;h:form&gt; 内的&lt;p:commandButton&gt; 时,不会调用selectedExtras 的setter 方法。当我检查在&lt;ui:repeat&gt; 的最后一个循环中创建的复选框并单击&lt;p:commandButton&gt; 时,我得到一个异常:

javax.el.PropertyNotFoundException: /lightbox-item.xhtml @57,165 value="#{cartBean.selectedExtras[iteration.index]}": null

【问题讨论】:

  • 您将需要发布更多代码。请发布一些支持 bean 代码。
  • @Catfish 我编辑了我的问题。实际上,我认为没有任何有趣的支持 bean 代码。正如您现在所看到的,#{item} 是来自&lt;ui:repeat&gt; 的变量,#{cartBean.selectedExtras} 指向List&lt;Item&gt; 的简单setter/getter 方法,就像#{item.items5} 是1,#{category.items} 也是一样。

标签: jsf-2 checkbox primefaces omnifaces selectmanycheckbox


【解决方案1】:

这个结构对我来说很好用。

正如the showcase page 中提到的,omnifaces.SelectItemsConverter 默认使用复杂对象的toString() 表示作为转换后的项目值。因此,如果您没有覆盖 toString() 方法(因此它仍然默认为 com.example.SomeClass@hashcode 在每次实例化时都会更改)并且 #{item} 托管 bean 是请求范围的,那么列表基本上会在每个 HTTP 请求上发生变化.这将导致“验证错误:值无效”错误。

如果你添加

<p:messages autoUpdate="true" />

<p:growl autoUpdate="true" />

这样您就可以在 UI 中获得所有(缺失的)验证/转换消息,那么您应该已经注意到了。

为了充分利用omnifaces.SelectItemsConverter,您应该相应地重写toString() 方法,以便它返回复杂对象的固定且唯一的表示。例如

@Override
public String toString() {
    return "Extra[id=" + id + "]";
}

或者,您可以将 #{item} 托管 bean 放在更广泛的范围内,例如视图范围。


更新关于您的更新,您将所有复选框组的选定值绑定到同一个 bean 属性#{cartBean.selectedExtras}。这样,每次迭代都会使用当前迭代轮次中的值覆盖该属性,直到您最终获得最后一次迭代的值。如果你在设置器上放置了一个调试断点,你就会注意到这一点。

这是不对的。它们应该各自指向不同的 bean 属性。从技术上讲,您应该拥有 #{item.selectedExtras} 作为属性。但我认为这在您当前的设计中没有意义。最好将#{cartBean.selectedExtras} 设为List&lt;Item[]&gt;Item[][]。这样你就可以根据迭代索引来设置它们,如下所示:

<ui:repeat var="item" value="#{category.items}" varStatus="iteration">
    <p:selectManyCheckbox id="extraCheckbox" value="#{cartBean.selectedExtras[iteration.index]}" layout="pageDirection" converter="omnifaces.SelectItemsConverter">  
         <f:selectItems value="#{item.items5}" var="extra" itemLabel="#{extra.name}"/>
    </p:selectManyCheckbox>
</ui:repeat>

如果是List&lt;Item[]&gt;,您只需确保使用空值预初始化selectedExtras 的次数与bean 的(后)构造函数中#{category.items} 的次数一样多。

for (Item item : category.getItems()) {
    selectedExtras.add(null);
}

如果是Item[][],你可以用

selectedExtras = new Item[category.getItems().size()];

【讨论】:

  • 感谢您的努力。可能我确实确实发布了小代码。实际上,在这种情况下,#{item} 是来自更高级别&lt;ui:repeat&gt; 的变量 - 似乎没有任何与范围相关的问题。而且我注意到,问题并不在于许多复选框,而只是关于我的前两个具有复选框的条目:setter 方法只是没有在前两个条目上调用。其他(也是)&lt;ui:repeat&gt;-created 条目及其复选框工作正常(调用 setter 方法)。
  • 嗯...这不是 &lt;ui:repeat&gt; 创建的前两个未调用 setter 的条目:它只是调用 setter 方法的最后一个条目。这是一个提示......但我仍然没有发现问题。
  • 我编辑了我的问题。非常抱歉在没有提供足够信息的情况下需要您的时间。我不清楚问题的背景,我总是担心发布大量不相关的代码。
  • 以后,你最好尝试用一个空白 bean 创建一个空白视图,然后用尽可能少的代码填充&lt;h:body&gt;,它可以自行演示/重现整个问题这样其他人应该能够通过将其复制粘贴到他们的环境中来做同样的事情。然后,将整个 &lt;h:body&gt; 内容复制到您的问题中。
  • 哇,这仍然让我很难受。在我有一个&lt;p:commandLink&gt; 而不是每个复选框之前,它与属性#{cartBean.selectedExtras} 一起工作。毫无疑问,就像你说的那样,但我并没有真正与我以前的方法有所不同,我只是头疼。你介意向我指出这个区别吗?我仍在努力实施您的方法。 A List of a List just on backing bean side 我以前曾经有过一次,但我绝对不熟悉 JSF 方面的 EL。提示更多信息? :D
猜你喜欢
  • 1970-01-01
  • 2016-06-22
  • 1970-01-01
  • 1970-01-01
  • 2020-12-25
  • 2020-02-23
  • 1970-01-01
  • 1970-01-01
  • 2017-03-31
相关资源
最近更新 更多