Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

<f:ajax render> not working via <composite:clientBehavior>

I have a composite component which has ajax:

<composite:interface>
    <composite:attribute name="question" required="true"/>
    <composite:attribute name="value" required="false"/>
    <composite:attribute name="id" required="true" />
    <composite:clientBehavior name="alter" 
        event="change" targets="input"/>
</composite:interface>
<composite:implementation>
    <label for="#{cc.attrs.id}">
        <h:outputText value="#{cc.attrs.question}" />
    </label>
    <div class="fld">      
        <h:selectOneRadio value="#{cc.attrs.value}" id="input">
            <f:selectItem itemValue="true" itemLabel="Yes" />
            <f:selectItem itemValue="false" itemLabel="No" />
        </h:selectOneRadio>
    </div>
</composite:implementation>

when I am using this composite component in my page like so:

<question:yesNo question="#{myMSG['knowRegQuestion']}" value="#{vehicle.regKnown}" id="is-reg-known">
    <f:ajax event="alter" render="reg-unknown" />
</question:yesNo>
......
<h:panelGroup id="reg-unknown" styleClass="questionGroup man-veh-srch">
    ......
    <h:selectOneListbox value="#{vehicle.model}" size="1" rendered="#{vehicle.regKnown eq 'true'}">
        ......
    </h:selectOneListbox>
</h:panelGroup>

The ajax is firing, the model is being updated correctly but the rendering does not change. (I have tried various EL expressions) Also the ajax response does not look correct in firebug:

<?xml version='1.0' encoding='UTF-8'?>
<partial-response id="j_id1"><changes><update id="j_id1:javax.faces.ViewState:0"><![CDATA[-2911901889097730230:4227240037100614528]]></update></changes></partial-response>

What have I missed? (thanks)

like image 644
Mark W Avatar asked May 22 '14 10:05

Mark W


1 Answers

Any relative client ID which is specified in <f:ajax render> is resolved relative to the parent ClientBehaviorHolder component in the component tree. In your particular case, this is actually the <h:selectOneRadio>. The component with client ID reg-unknown is thus being sought in the same naming container parent as the <h:selectOneRadio>, which is the <cc:implementation> itself (you probably already know that composite components implement NamingContainer). However, the desired component isn't in there.

You'd better specify an absolute client ID instead (thus, starting with :, so that it would be sought relative to the UIViewRoot). You can achieve this in two general ways:

  1. Hardcode it (assuming that this all is inside a form with ID form):

    <h:form id="form">
        <question:yesNo ...>
            <f:ajax event="alter" render=":form:reg-unknown" />
        </question:yesNo>
        ...
        <h:panelGroup id="reg-unknown" ...>
            ...
        </h:panelGroup>
    </h:form>
    
  2. Reference UIComponent#getClientId() (in case ID of parent naming container isn't known):

    <h:form ...>
        <question:yesNo ...>
            <f:ajax event="alter" render=":#{regUnknown.clientId}" />
        </question:yesNo>
        ...
        <h:panelGroup binding="#{regUnknown}" ...>
            ...
        </h:panelGroup>
    </h:form>
    

This is indeed awkward. This was ever reported as Mojarra issue 1510, but they didn't consider it to be a bug as the composite component itself isn't supposed to know anything about other components outside the composite component (although the solution would be theoretically simple: if the <f:ajax render> doesn't start with : or @, then prefix it with the client ID of the composite component's parent).

like image 111
BalusC Avatar answered Sep 28 '22 09:09

BalusC