Rerendering composite component by ajax
Asked Answered
A

1

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?

Anglin answered 22/8, 2013 at 11:53 Comment(0)
A
5

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:

Averell answered 22/8, 2013 at 13:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.