同一页面中多次包含组件时绑定失败
Binding fails when a component is included multiple times in same page
我有以下情况:
<p:selectBooleanCheckbox id="couponAgreement">
<h:panelGroup rendered="#{!couponAgreement.valid}">
是否可以通过id获取组件?设置 binding
就可以了,但是当我在我的 JSF 页面中多次包含它时,只呈现最后一个实例。
我想象的是这样的:
<h:panelGroup rendered="#{!fn:getComponentById('couponAgreement').valid}">
您可以为此使用 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
// ...
}
在设计得当的复合材料中,您通常已经拥有或最终需要它。
我有以下情况:
<p:selectBooleanCheckbox id="couponAgreement">
<h:panelGroup rendered="#{!couponAgreement.valid}">
是否可以通过id获取组件?设置 binding
就可以了,但是当我在我的 JSF 页面中多次包含它时,只呈现最后一个实例。
我想象的是这样的:
<h:panelGroup rendered="#{!fn:getComponentById('couponAgreement').valid}">
您可以为此使用 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
// ...
}
在设计得当的复合材料中,您通常已经拥有或最终需要它。