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:
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…