在同一页面中多次包含组件时,绑定失败

时间:2015-08-21 15:03:39

标签: jsf binding components

我有以下情况:

<p:selectBooleanCheckbox id="couponAgreement">
<h:panelGroup rendered="#{!couponAgreement.valid}">

是否可以通过其ID获取组件?设置binding会这样做,但是当我在我的JSF页面中多次包含它时,只渲染最后一个实例。

我想象这样的事情:

<h:panelGroup rendered="#{!fn:getComponentById('couponAgreement').valid}">

1 个答案:

答案 0 :(得分:2)

您可以使用UIComponent#findComponent()。它将相对于命名容器父级进行搜索。因此,如果您可以保证这些组件具有唯一的命名容器父级(例如<ui:repeat><f:subview><h:form>等),那么请执行以下操作:

<h:someInput id="someInput" ... />
<h:someOutput ... rendered="#{component.findComponent('someInput').valid}" />

对于binding,您应该确保binding属性的值仅与组件本身绑定,而不是跨多个组件共享。

因此,当涉及可重用的include / tagfile / composite中的组件时,这是错误的:

<h:someInput binding="#{someInput}" ... />
<h:someOutput ... rendered="#{someInput.valid}" />

而是将其绑定到唯一键。让include / tagfile / composite需要id param / attribute,然后使用<c:set>创建一个附加id的变量,以便最终可以将其用作请求范围映射的键

<c:set var="binding" value="binding_someInput_#{id}" />
<h:someInput id="#{id}" binding="#{requestScope[binding]}" ... />
<h:someOutput ... rendered="#{requestScope[binding].valid}" />

要保持请求范围干净,请考虑通过faces-config.xml

在请求范围内创建哈希映射
<managed-bean>
    <description>Holder of all component bindings.</description>
    <managed-bean-name>components</managed-bean-name>
    <managed-bean-class>java.util.HashMap</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<h:someInput id="#{id}" binding="#{components[id]}" ... />
<h:someOutput ... rendered="#{components[id].valid}" />

对于复合材料组件,还有另一种方法。将它绑定到支持组件。

<cc:interface componentType="someComposite">
    ...
</cc:interface>
<cc:implementation>
    <h:someInput binding="#{cc.someInput}" ... />
    <h:someOutput ... rendered="#{cc.someInput.valid}" />
</cc:implementation>
@FacesComponent("someComposite")
public class SomeComposite extends UINamingContainer {

    private UIInput someInput; // +getter+setter

    // ...
}

在一个设计合理的复合材料中,无论如何你经常已经或最终需要它。