1

I have a Composite Component that uses ajax to change multiple elements when an item is selected. I am also using Primefaces p:ajax and p:commandButton instead of f:ajax if that makes any difference.

The problem is I cannot find the right update attribute to use on the components so that the whole component updates. For example, in the following button:

<p:commandButton id="slGoUSA"
         value="USA" 
         rendered="#{cc.USAButtonOn}"
         actionListener="#{cc.doSetUSA}"
         update="???"  />

I have tried all the following and none of them work:

update="@this"
update="@form"
update="#{cc.clientId}"
update=":#{cc.clientId}"
update="#{cc.clientId}:localID"
update=":#{cc.clientId}:localID"

The only thing that does work is this:

update="#{cc.attrs.update}"

and then the client page passes some clientId that includes the composite component. However I don't want to force the user to include an update parameter in the component invocation. Is there a convenient way of doing this?


Update

Ok I think it might help if I showed a complete test case. I implement a UINamingContainer to back the composite component like this:

/*
 * Test code
 */
package com.myapp.app.component;

import java.io.Serializable;
import javax.faces.component.FacesComponent;
import javax.faces.component.UINamingContainer;

@FacesComponent(value="qctest")
public class Qctest extends UINamingContainer implements Serializable {

private enum StateKey { Counter }

public Qctest() { }

@Override
public String getFamily() { return "javax.faces.NamingContainer"; }

public Integer getCounter() {
    Integer i = (Integer) getStateHelper().get(StateKey.Counter);
    if (i == null) i = Integer.valueOf(1);
    else i += 1;
    getStateHelper().put(StateKey.Counter, i);
    return i;
}
}

Then the cc definition looks like this:

<!-- INTERFACE -->
<cc:interface componentType="qctest">
</cc:interface>

<!-- IMPLEMENTATION -->
<cc:implementation>
    
    <h:outputText id="outText" value="Counter is now: #{cc.counter}" />
    <br/>
    <p:commandButton value="Hit Me" update=":#{cc.clientId}" />
    <br/>
    <h:commandButton value="Or Hit Me" >
        <f:ajax render=":#{cc.clientId}"/>
    </h:commandButton>
    
</cc:implementation>
</html>

This code is basically the OMG my first AJAX page ever! application, except it is inside a composite component instead of a regular page with normal backing bean.

Neither button succeeds in doing the update. Firebug shows the XHR being sent, but the response does not update the counter. None of the different values for update or render works. In the case shown, the primefaces button seems to do nothing, in the case of the JSF command button I get a dialog box that says:

malformedXML: During update: test2form:xyz not found

This seems to me to be the most trivial use of AJAX inside a Composite Component. Can anyone explain what could be going on?

Community
  • 1
  • 1
AlanObject
  • 9,613
  • 19
  • 86
  • 142

1 Answers1

1

malformedXML: During update: test2form:xyz not found

You're right, there's no one HTML element in the generated HTML DOM tree which has exactly that ID. The composite component's content is by itself not wrapped in some generic HTML element which is reachable by JavaScript. You'd basically need to bring in some container component:

<cc:implementation>
    <h:panelGroup id="container">  
        ...
        <h:commandButton value="submit">
            <f:ajax render="container" />
        </h:commandButton>
        ...
        <p:commandButton value="submit" update="container" />
        ...
    </h:panelGroup>
</cc:implementation>

But I still wonder why @form didn't work for you. It works for me.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • I thought I tried this but now I will try it on my test case and report back. – AlanObject Dec 16 '11 at 19:13
  • OK I just tried it and both suggestions work on my test case. I can get an update on an internal container and the '@form'. So I will have to go back to see why it doesn't work on my regular application, but I suspect I have some PrimeFaces javascript to read before it is done. One peculiarity though -- when using `@form` I get an error message in the log saying "Cannot find component with identifier "test2form" in view" -- where test2form is the id attribute value of my form. – AlanObject Dec 16 '11 at 19:21
  • Is this with Mojarra 2.1.4? By the way your overriden `getFamily()` method is unnecessary. The extended `UINamingContainer` class has already the same implementation. It's only necessary when you implement `NamingContainer` interface. – BalusC Dec 16 '11 at 19:37