小编典典

通过Ajax渲染复合组件

ajax

我建立了一个复合组件,看起来像这样:

<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>

组件正确显示当前标签。

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

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

现在,当执行该动作时,什么也不会发生。但是,当我将Postfix添加到组件中的ID时,它可以正常工作(请参见下文)。

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

并使用后缀在render中定义ID:

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

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

有人可以向我解释为什么仅当我在ID中添加后缀时才起作用h:panelGroup吗?


阅读 303

收藏
2020-07-26

共1个答案

小编典典

这个问题实际上有两个方面。

第一个问题是,<xyz:comp id>实际上指定复合部件的ID 本身
<cc:implementation>。默认情况下,HTML输出中不显示该位置,因此ajax /
JavaScript不能被document.getElementById()and friends 找到。

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

<span id="idMyComponent:idMyComponent">

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

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

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

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

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

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

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

2020-07-26