jsf-2 - ui 内的 Primefaces ManyCheckbox :repeat calls setter method only for last loop

标签 jsf-2 checkbox primefaces omnifaces selectmanycheckbox

我有一个<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/

相关文章:

jsf-2 - 从jsf中的另一个表单更新一个表单内容

jsf-2 - 如何通过 RequestContext 更新

excel - 启用文本框的动态复选框

java - JavaScript 和 JSF 如何协同工作?

jsf - 获取 p :dataTable of dynamic element 中的行号

java - ManagedBean 中的 primefaces 自动完成事件 itemSelect 监听器值 null

jsf - 是否可以禁用 f :event type ="preRenderView" listener on postback?

php - 如何在 WordPress 小部件中保存复选框数组?

javascript - 类型错误 : Cannot assign to read only property 'checked' checkbox

jsf-2 - 使用 <p :fileUpload > with the <h:inputText> doesn't get the inputext mapping value while uploading