【问题标题】:Binding fails when a component is included multiple times in same page同一页面中多次包含组件时绑定失败
【发布时间】:2015-11-15 14:20:01
【问题描述】:

我有以下情况:

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

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

我想像这样:

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

【问题讨论】:

  • &lt;p:selectBooleanCheckbox binding="#{component}"/&gt; 然后在 EL 中 #{component.clientId}
  • 正如我所说,绑定不起作用,因为我多次包含它..顺便说一句,我不需要 clientid
  • 组件可以被唯一标识,如果包含在像&lt;f:subview&gt;这样的命名容器中。
  • 您是否有任何理由不想通过 ajax 更新来执行此操作,在您的支持 bean 中设置一些布尔值,并将其用作您的 rendered 条件?
  • @Tiny 我用子视图标签包围了包含标签,但结果相同:只显示最后一个复选框

标签: jsf binding components


【解决方案1】:

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

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

对于binding,您只需确保binding 属性的值仅与组件本身相关联,而不是在多个组件之间共享。

因此,当涉及可重用的包含/标记文件/复合中的组件时,这是错误的:

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

宁可将其绑定到唯一键。让 include/tagfile/composite 需要 id 参数/属性,然后使用 &lt;c:set&gt; 创建一个附加 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

    // ...
}

在精心设计的复合材料中,您通常已经拥有或最终需要它。

【讨论】:

  • 感谢这个详细的例子!似乎“cc.findComponent('couponAgreement').valid”也可以完成这项工作,你怎么看?包含似乎被处理为 cc 上下文
  • 你确实可以这样做。
猜你喜欢
  • 2019-07-09
  • 1970-01-01
  • 2012-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-29
  • 2014-07-24
  • 1970-01-01
相关资源
最近更新 更多