在ui中的Primefaces ManyCheckbox:仅针对最后一个循环重复调用setter方法

时间:2012-10-30 20:54:41

标签: jsf-2 checkbox primefaces omnifaces selectmanycheckbox

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

1 个答案:

答案 0 :(得分:2)

这个结构适合我。

正如其他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()方法,以便它返回复杂对象的固定且唯一的表示。 E.g。

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

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


对于您的更新

更新,您将所有复选框组的选定值绑定到同一个 bean属性{{1} }。这样,每次迭代都会使用当前迭代轮次中的值覆盖属性,直到您最终获得最后一次迭代的值。如果您在setter上放置了一个调试断点,那么您已经注意到了。

这是不对的。它们应该指向不同的bean属性。从技术上讲,您应该拥有#{cartBean.selectedExtras}作为财产。但我认为这在你目前的设计中毫无意义。最好是将#{item.selectedExtras}设为#{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[]>初始化为空值的次数与bean的(post)构造函数中的selectedExtras一样多。

#{category.items}

如果是for (Item item : category.getItems()) { selectedExtras.add(null); } ,则可以使用

Item[][]