这个结构对我来说效果很好。
正如其中提到的展示页面 http://showcase.omnifaces.org/converters/SelectItemsConverter, the omnifaces.SelectItemsConverter
默认情况下使用toString()
将复杂对象表示为转换后的项目值。所以如果你没有覆盖toString()
方法(因此它仍然默认为com.example.SomeClass@hashcode
在每个实例化时都会改变)和#{item}
托管 bean 是请求范围的,那么该列表基本上会在每个 HTTP 请求上发生变化。这将导致“验证错误:值无效”错误。
如果你添加
<p:messages autoUpdate="true" />
or
<p:growl autoUpdate="true" />
这样您就可以在 UI 中获得所有(丢失的)验证/转换消息,那么您应该已经注意到了。
为了利用omnifaces.SelectItemsConverter
在最好的情况下,你应该覆盖toString()
相应的方法,以便它返回复杂对象的固定且唯一的表示。例如。
@Override
public String toString() {
return "Extra[id=" + id + "]";
}
或者,您可以将#{item}
托管 bean 的范围更广,例如视图范围。
Update至于您的更新,您正在绑定所选的值all复选框组到一且相同豆属性#{cartBean.selectedExtras}
。这样,每次迭代都会使用当前迭代轮次的值覆盖该属性,直到最终得到最后一次迭代的值。如果您在设置器上放置了调试断点,您就会注意到这一点。
这个不对。它们应该各自指向不同的 bean 属性。从技术上讲,你应该有一个#{item.selectedExtras}
作为财产。但我认为这在你当前的设计中没有意义。更好的是使#{cartBean.selectedExtras}
an List<Item[]>
or 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()];