title: JSF2 Composite component link using ajax
body: <p>Here is my (simplified) issue :<br/>
  I've got a page that is using 2 composite components of mine :<br />
   - CCSelection<br/>
   - CCDisplay<br />
  <br />
  In CCSelection, I have a list of values, each one has got a h:commandLink onto.<br />
  When clicking on a link, the CCDiaplay component is refreshed using the selected value.<br />
  To do this, CCSelection exposes a method attribute that is directly linked on each h:commandLink. The value is given to the method using f:attribute.<br />
  In the page backing bean, I've got a method (that is given to CCSelection as an attribute), that sets a member.<br />
  CCDisplay gets this value though an cc:attribute via the pages's member's getter.<br />
  It works !<br />
  Now, I want to ajaxize this behaviour.<br />
  <br />
  I tryed to put an f:ajax for each h:commandLink in CCSelection... but if I put @form or @all in the render attribute, nothing is rendered (but the setter methods are called). If I put the id of the UIComponent (of the Page) to render, I get a nullpointerexception saying that a property is not defined for NamingContainer in CCDisplay. Quite strange because I didn't change anything inside CCDisplay !<br />
  <br />
  I think the solution is to put the f:ajax not inside CCSelection but in Page. <br />
  So there may be 2 ways to achieve this :<br />
   - CCSelection raises an event f:ajax can manage... but how ?<br />
   - Using cc:clientBehaviour for CCSelection. But is it possible to target more that 1 <br />component (I've got many h:commandLink, but I want only 1 event).<br />
   - Other ways ?<br />
  <br />
  <br />
  Here is a pseudo code</p>
  
  <p>page.xhtml<br /></p>
  
  <pre><code>&lt;myComp:ccSelection actionMethod="#{pageBean.select}"
                      render="#{clientIDHelper.clientId['display']}" /&gt;
  &lt;h:panelGroup id="diplay" binding="#{clientIDHelper.bindings['display']}"&gt;
    &lt;myComp:ccDisplay value="#{pageBean.value}" /&gt;
  &lt;/h:panelGroup&gt;
  </code></pre>
  
  <p>To recover the full clientid of the panel containing the ccDiaplay composite component, I use a clientIDMap technic described <a href="https://www.xing.com/net/jsf/newsletters-archive-362954/group-newsletter-the-map-hack-26501345/" rel="nofollow">here</a>.</p>
  
  <p>PageBean.java</p>
  
  <pre><code>private String _value;
  
  public String getValue() { return _value; }
  public void setValue(String value) [ _value = value; }
  
  public void select(String value) {
    setValue(value);
  }
  </code></pre>
  
  <p>ccSelection.xhtml</p>
  
  <pre><code>&lt;cc:interface&gt;
    &lt;cc:attribute method-signature="void selectAction(String)"
                  name="actionMethod" /&gt;
    &lt;cc:attribute name="render" /&gt;
  &lt;/cc:interface&gt;
  &lt;cc:implementation&gt;
    &lt;t:dataTable value="#{cc.values}"
                 var="val"
                 ...
                 &gt;
      &lt;h:column&gt;
         &lt;t:commandLink actionListener="#{cc.selectionValueListener}"
           &lt;f:ajax render="#{cc.attrs.render}" /&gt;
           &lt;f:attribute name="value"
                        value="#{val}" /&gt;
         &lt;/t:commandLink&gt;
      &lt;/h:column&gt;
    &lt;/t:dataTable&gt;
  &lt;/cc:implementation&gt;
  </code></pre>
  
  <p>ccSelection.java</p>
  
  <pre><code>public void selectionValueListener() {
    // recover the attribute value
    String value = event.getComponent().getAttributes().get("value");
    // call the callback method of the page
    FacesContext context = FacesContext.getCurrentInstance();
    MethodExpression method = (MethodExpression) this.getAttributes().get("actionMethod");
    if (method != null)
      method.invoke(context.getELContext(), new Object[] {value});
  }
  </code></pre>
  
  <p>I don't think ccDisplay is interressting.<br />
  <br />
  So, if I don't put the f:ajax tag, it works.
  When I put the f:ajax with the render pointing to the clientId passed in param, I get an error while loading the page.
  If I change the render for @form or @all, the pageBean.select method is called, but ccDisplay is not refreshed.</p>