我有一个<p:selectManyCheckbox>
里面<ui:repeat>
,从某个对象类的列表(由 <ui:repeat>
-变量提供)获取其项目,并且应该将所选项目保存到同一对象类的另一个列表中。但它调用了setter方法#{cartBean.setSelectedExtras}
仅适用于最后一个条目( <ui:repeat>
的最后一次迭代)。
<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>>();
当我选中 <ui:repeat>
的第一个循环创建的复选框时然后单击<p:commandButton>
里面一样<h:form>
selectedExtras
的setter方法不被调用。当我检查 <ui:repeat>
的最后一个循环中创建的复选框时然后单击<p:commandButton>
我收到异常:
javax.el.PropertyNotFoundException: /lightbox-item.xhtml @57,165 value="#{cartBean.selectedExtras[iteration.index]}": null
最佳答案
这个结构对我来说效果很好。
正如 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,例如 View 范围。
更新对于您的更新,您将所有复选框组的选定值绑定(bind)到一个相同 bean 属性 #{cartBean.selectedExtras}
。这样,每次迭代都会使用当前迭代轮次的值覆盖该属性,直到最终得到最后一次迭代的值为止。如果您在 setter 上放置了调试断点,您就会注意到这一点。
这是不对的。它们应该各自指向不同的 bean 属性。从技术上讲,您应该有一个 #{item.selectedExtras}
作为属性(property)。但我认为这在你当前的设计中没有意义。更好的办法是制作 #{cartBean.selectedExtras}
一个List<Item[]>
或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<Item[]>
您只需要确保预初始化 selectedExtras
空值的次数与 #{category.items}
的次数一样多在 bean 的(后)构造函数中。
for (Item item : category.getItems()) {
selectedExtras.add(null);
}
如果是Item[][]
,你就足够了
selectedExtras = new Item[category.getItems().size()];
关于jsf-2 - ui 内的 Primefaces ManyCheckbox :repeat calls setter method only for last loop,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13147440/