通过ajax重新渲染复合组件 [英] Rerendering composite component by ajax
问题描述
我已经构建了一个看起来像这样的复合组件:
<composite:attribute name="id" required="false"/><composite:attribute name="label" required="true"/></composite:interface><复合:实现><h:panelGroup id="#{cc.attrs.id}"><fieldset class="fieldset"><legend>${cc.attrs.label}</legend></fieldset></h:panelGroup></composite:implementation>
该组件正确显示当前标签.
...<a4j:ajax ... render="idMyComponent"/>...
现在当动作被执行时,什么都不会发生.但是,当我向组件中的 ID 添加 Postfix 时,它工作正常(见下文).
<代码>...<复合:实现><h:panelGroup id="#{cc.attrs.id}Label">...
并用后缀定义渲染中的ID:
...<a4j:ajax ... render="idMyComponentLabel"/>...
有人可以向我解释为什么它只在我向 h:panelGroup
中的 ID 添加后缀时才有效吗?
这个问题其实有两个方面.
第一个问题是
实际上指定了复合组件本身的ID,document.getElementById()
和朋友找到它.
实际上,您的 <h:panelGroup id="#{cc.attrs.id}">
最终生成的 HTML 输出如下(右键单击页面和 View来源自己看):
第二个问题"是 RichFaces/Ajax4jsf 通过不仅在当前 NamingContainer<的上下文中搜索,增强了通过相对客户端 ID(即不以
:
开头)树中 JSF 组件的引用/查找/code>,但也适用于所有其他 NamingContainer
组件.复合组件本质上也是一个 NamingContainer
组件.
您的第一次尝试失败了,因为它找到了组合本身而不是面板组,但是 JS/ajax 又未能更新,因为不存在任何带有 id="myComponent"
在生成的 HTML 输出中.
您的第二次尝试成功了,因为它终于找到了真正的面板组(注意:因为它还搜索了所有其他 NamingContainer
组件;如果您使用了 < 这仍然会失败;f:ajax>
而不是
).
解决问题的正确方法不是在 JSF 组件上使用 #{cc.attrs.id}
,而是在 JSF 组件上使用 #{cc.clientId}
纯 HTML 元素.
(是的,在内部使用 或
)这种方式 JSF 可以通过客户端 ID 找到组件(为了生成正确的 ajax 响应)和 JS 可以通过客户端 ID 找到 HTML 元素(为了更新正确的 HTML 元素基于关于 ajax 响应).
另见:
- 是否可以使用 JSF 更新非 JSF 组件(纯 HTML)阿贾克斯?
- 以简洁的方式将 JavaScript 集成到 JSF 复合组件中
- 如何找出组件的客户端 ID 进行 ajax 更新/渲染?找不到带有表达式foo"的组件引用自bar"
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
?
This problem is actually two-fold.
The first problem is that the <xyz:comp id>
actually specifies the ID of the composite component itself, the <cc:implementation>
. This is by default nowhere represented in HTML output and therefore ajax/JavaScript can't locate it by document.getElementById()
and friends.
Actually, your <h:panelGroup id="#{cc.attrs.id}">
ends up in generated HTML output as follows (rightclick page and View Source to see it yourself):
<span id="idMyComponent:idMyComponent">
The second "problem" is that RichFaces/Ajax4jsf has enhanced the referencing/finding of JSF components in the tree by relative client ID (i.e. not starting with :
) by not only searching in the context of the current NamingContainer
, but also in all other NamingContainer
components. A composite component is inherently also a NamingContainer
component.
Your first attempt failed because it found the composite itself instead of the panel group, but JS/ajax in turn failed to update because there doesn't exist any HTML element with id="myComponent"
in the generated HTML output.
Your second attempt succeeded because it finally found the real panel group (note: because it also searched in all other NamingContainer
components; this would still have failed if you've used <f:ajax>
instead of <a4j:ajax>
).
The right way to fix your problem is not using #{cc.attrs.id}
on a JSF component, but using #{cc.clientId}
on a plain HTML element.
<span id="#{cc.clientId}">
(yes, use a <span>
or <div>
instead of <h:panelGroup>
inside the <cc:implementation>
)
This way JSF can find the component by client ID (in order to generate the proper ajax response) and JS can find the HTML element by client ID (in order to update the right HTML element based on ajax response).
See also:
- Is it possible to update non-JSF components (plain HTML) with JSF ajax?
- Integrate JavaScript in JSF composite component, the clean way
- How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
这篇关于通过ajax重新渲染复合组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!