1

I have build a composite component witch looks something like this:

<composite:interface>
  <composite:attribute name="id" required="false" />
  <composite:attribute name="label" required="true" />
</composite:interface>

<composite:implementation>
  <h:panelGroup id="#{cc.attrs.id}">
    <fieldset class="fieldset"><legend>${cc.attrs.label}</legend></fieldset>
  </h:panelGroup>  
</composite:implementation>

The compent displays the current label correctly.

<xyz:comp id="idMyComponent" label="#{someBean.text}"/>

...
<a4j:ajax ... render="idMyComponent" />
...

Now when the action is preformed nothing happens. However when I add a Postfix to the ID in the component it works fine (see below).

...
<composite:implementation>
      <h:panelGroup id="#{cc.attrs.id}Label">
...

And define the ID in render with the postfix:

<xyz:comp id="idMyComponent" label="#{someBean.text}"/>

...
<a4j:ajax ... render="idMyComponentLabel" />
...

Can some on explain to me why it only works when I add a postfix to the ID in h:panelGroup?

4

1 回答 1

5

这个问题实际上是双重的。

第一个问题是,<xyz:comp id>实际上指定了复合组件本身的 ID ,即<cc:implementation>. 默认情况下,这在 HTML 输出中无处表示,因此 ajax/JavaScript 无法通过document.getElementById()和朋友找到它。

实际上,您<h:panelGroup id="#{cc.attrs.id}">最终生成的 HTML 输出如下(右键单击页面并查看源代码以自己查看):

<span id="idMyComponent:idMyComponent">

:第二个“问题”是 RichFaces/Ajax4jsf不仅在 current 的上下文中搜索NamingContainer,而且还在所有其他NamingContainer组件的上下文中搜索,增强了通过相对客户端 ID(即不以 开头)在树中的 JSF 组件的引用/查找。复合组件本质上也是一个NamingContainer组件。

您的第一次尝试失败了,因为它找到了组合本身而不是面板组,但是 JS/ajax 又无法更新,因为生成的 HTML 输出中不存在任何 HTML 元素id="myComponent"

您的第二次尝试成功了,因为它终于找到了真正的面板组(注意:因为它还在所有其他NamingContainer组件中进行了搜索;如果您使用<f:ajax>而不是 ,这仍然会失败<a4j:ajax>)。

解决问题的正确方法不是#{cc.attrs.id}在 JSF 组件上使用,而是#{cc.clientId}在纯 HTML 元素上使用。

<span id="#{cc.clientId}">

(是的,使用<span>or<div>代替<h:panelGroup>内部<cc:implementation>

这样,JSF 可以通过客户端 ID 找到组件(以便生成正确的 ajax 响应),而JS 可以通过客户端 ID 找到 HTML 元素(以便根据 ajax 响应更新正确的 HTML 元素)。

也可以看看:

于 2013-08-22T13:41:16.687 回答