How to load a JSF 2.0 composite component via AJAX - ajax

I have designed a composite component that looks something like this:
<cc:interface>
<cc:attribute name="value" required="true" />
<cc:attribute name="title" required="true" />
</cc:interface>
<!-- IMPLEMENTATION -->
<cc:implementation>
<div class="inputTile">
<div class="inputTitle">
<span>#{cc.attrs.title}</span>
</div>
<div class="inputTileContent">
<input type="text" value="#{cc.attrs.value}" />
</div>
</div>
</cc:implementation>
I am trying to load this onto a div on my web page through AJAX.
Any ideas on how to do that?

Something like this maybe?
<h:panelGroup id="foo" layout="block">
<your:composite rendered="#{bean.loadCompositeInDiv}" />
</h:panelGroup>
<h:commandButton value="Load composite in div" action="#{bean.setLoadCompositeInDiv(true)}">
<f:ajax render="foo" />
</h:commandButton>
with
#ManagedBean
#ViewScoped
public class Bean {
private boolean loadCompositeInDiv;
// Getter+setter
}

Related

f:ajax not rendering h:selectManyListbox

Using f:ajax component with h:selectManyListbox, it is firing the listener method but not refreshing the rendering list.
I have Market. When I select market it needs to display Sub-Markets. Initial page load will have all the Markets and Sub-Markets, but it needs to filter when user selects "Market".
Using below code:
<ui:fragment id="uda2" rendered="#{udaList.index eq 1}">
<div class=" row form-group" >
<label class="col-sm-2" for="sel-service">Market:</label>
<div class="col-sm-10">
<h:selectManyListbox style="width:360px;" multiple="" pt:aria-required="true" required="required" pt:data-toggle="chosen"
disabled="# {licenseSelectionBean.isFieldEnabled(FormFieldsEnum.ITEM_UDA2)}"
id="#{FormFieldsEnum.ITEM_UDA2.getFieldCode()}" size="1"
name="#{FormFieldsEnum.ITEM_UDA2.getFieldCode()}"
value="#{licenseSelectionBean.selectedItemUda2}"
styleClass="sel-chosen">
<f:selectItems var="uda2"
value="#{licenseSelectionBean.selectUda2}" />
<f:ajax event="change" execute="#this" render="#this udalist3"
listener="#{licenseSelectionBean.onChangeFilter()}" />
</h:selectManyListbox>
</div>
</div>
</ui:fragment>
<ui:fragment rendered="#{udaList.index eq 2}">
<div class="row form-group" >
<label class="col-sm-2" for="sel-service">Sub-Market:</label>
<div class="col-sm-10">
<h:selectManyListbox style="width:360px;" multiple="" pt:aria-required="true" required="required" pt:data-toggle="chosen"
disabled="#{licenseSelectionBean.isFieldEnabled(FormFieldsEnum.ITEM_UDA3)}"
size="1"
pt:name="udalist3"
value="#{licenseSelectionBean.selectedItemUda3}"
pt:id="udalist3"
styleClass="sel-chosen">
<f:selectItems var="uda3"
value="#{licenseSelectionBean.selectUda3}" />
<!-- <f:ajax render="#{FormFieldsEnum.ITEM_UDA4.getFieldCode()}"
listener="#{licenseSelectionBean.onChangeFilter()}" /> -->
</h:selectManyListbox>
</div>
</div>
</ui:fragment>
Used "pt" for pass-through because JSF prefixing dynamic id.
How to resolve this problem?
Simple solution. Replace
<f:ajax event="change" execute="#this" render="#this udalist3"
listener="#{licenseSelectionBean.onChangeFilter()}" />
with
<f:ajax event="change" execute="#this" render="#form"
listener="#{licenseSelectionBean.onChangeFilter()}" />
This might cause some unnecesarry traffic. You can also encapsulate the second ui:fragment in a panelgroup, e.g.
<h:panelGroup id="wrapper">
<ui:fragment rendered="#{udaList.index eq 2}">
....
</h:panelgroup>
and add replace "udalist3" with "wrapper" in the f:ajax render attribute.

Spring webflow cleaning form fields

I use the same bean field, a string called email, for different purposes (register, recovery password, login). So, I wish navigate between views/flows and bean fields must clean automatically, but this behavior don't happen.
It's a JSF2/Spring project
Flow definition
<var name="viewScope.loginFields" class="es.project.viewBean.ConnectionFields" />
<view-state id="login" view="login.xhtml" model="loginFields">
<transition on="entry" to="connect"/>
<transition on="recoveryPass" to="recovery" />
</view-state>
<view-state id="recovery" view="recovery.xhtml" model="loginFields">
<transition on="return" to="login" />
<transition on="sendPass" to="recoveryPass" />
</view-state>
Bean definition
#Service("loginFields")
public class ConnectionFields implements Serializable {
private static final long serialVersionUID = 1L;
private static Logger logger=LogManager.getLogger(ConnectionFields.class);
#NotNull(message="{field.notEmpty.validation}")
#Email(message="{field.email.validation}")
private String email;
#NotNull(message="{field.notEmpty.validation}")
#Size(min=6,max=12,message="{field.size.validation}")
#Pattern(regexp="^[a-zA-Z0-9]*$",message="{field.onlyAlpha.validation}")
private String password;
#NotNull(message="{field.notEmpty.validation}")
#Size(min=6,max=12,message="{field.size.validation}")
#Pattern(regexp="^[a-zA-Z0-9]*$",message="{field.onlyAlpha.validation}")
private String passwordRepeated;
#NotNull(message="{field.notEmpty.validation}")
#Email(message="{field.email.validation}")
private String emailRepeated;
...........
...........
...........
}
recovery.xhtml
<h:form id="formRecovery">
<h:panelGroup layout="block" id="containerFormRecovery" styleClass="containerFormRecovery">
<p:focus />
<h:panelGroup layout="block" styleClass="formRecovery-row">
<h:outputLabel for="email" value="#{msg['email.txt']}" />
<h:inputText id="email" value="#{loginFields.email}" title="#{msg['email.txt.title']}" alt="#{msg['email.txt.alt']}" styleClass="#{component.valid ? '' : 'invalid'}" size="35" tabindex="1">
<f:validateBean for="email" />
<p:ajax event="blur" update="#this emailError"/>
</h:inputText>
<h:message for="email" id="emailError" styleClass="messageError" />
</h:panelGroup>
<h:panelGroup layout="block" styleClass="formRecovery-row">
<p:captcha id="captcha" theme="white" requiredMessage="#{msg['captcha.required']}" tabindex="2">
</p:captcha>
<h:message for="captcha" id="captchaError" styleClass="messageError"/>
</h:panelGroup>
<h:panelGroup layout="block" id="containerRecoveryButtons" styleClass="containerRecoveryButtons">
<h:commandButton value="#{msg['send.btn']}" title="#{msg['send.btn.title']}" alt="#{msg['send.btn.title']}" action="sendPass" tabindex="3" />
</h:panelGroup>
</h:panelGroup>
</h:form>
<h:panelGroup>
<h:commandLink value="#{msg['return.btn']}" title="#{msg['return.btn.title']}" alt="#{msg['return.btn.alt']}" action="return" tabindex="4" />
</h:panelGroup>
login.xthml
<h:form id="formLogin">
<h:panelGroup layout="block" id="containerFormLogin" styleClass="containerFormLogin">
<p:focus />
<h:panelGroup layout="block" styleClass="formLogin-row">
<h:outputLabel for="email" value="#{msg['email.txt']}" />
<h:inputText id="email" value="#{loginFields.email}" title="#{msg['email.txt.title']}" alt="#{msg['email.txt.alt']}" styleClass="#{component.valid ? '' : 'invalid'}" size="35" tabindex="2">
<f:validateBean for="email" />
<p:ajax event="blur" update="#this emailError" />
</h:inputText>
<h:message for="email" id="emailError" styleClass="messageError" />
</h:panelGroup>
<h:panelGroup layout="block" styleClass="formLogin-row">
<h:outputLabel for="password" value="#{msg['pass.txt']}" />
<p:password id="password" value="#{loginFields.password}" title="#{msg['pass.txt.title']}" alt="#{msg['pass.txt.alt']}"
styleClass="#{component.valid ? '' : 'invalid'}" size="35" tabindex="3">
<f:validateBean for="password" />
<p:ajax event="blur" update="#this passwordError" />
</p:password>
<h:message for="password" id="passwordError" styleClass="messageError" />
</h:panelGroup>
<p>
<h:outputLabel for="remember" value="#{msg['rememberSession.msg.check']}" />
<h:selectBooleanCheckbox id="remember" value="#{loginFields.remember}" tabindex="4" title="#{msg['rememberSession.title.check']}" />
</p>
<h:panelGroup layout="block" id="containerLoginButtons" styleClass="containerLoginButtons">
<h:commandButton value="#{msg['login.long.btn']}" action="entry" tabindex="5" title="#{msg['login.long.btn.title']}" alt="#{msg['login.long.btn.alt']}" />
</h:panelGroup>
</h:panelGroup>
</h:form>
<p>
<h:form>
<h:commandLink value="#{msg['recoveryPassword.msg.link']}" action="recoveryPass" />
</h:form>
</p>
On above example, my idea is to navigate to RecoveryPassword page from Login page and viceversa, and I would like email field reset value itself when I change view, but email never reset the value.
One approach would be to clear the value in the <transition> or the <on-entry> of your states. Either with just a setter method or with a custom method (e.g. reset()). We do this for various other conditions where entering a state requires clearing a field.
e.g.
<view-state id="recovery">
<on-entry>
<set name="loginFields.email" value="''"/>
</on-entry>
...
</view-state>

Bean scope loss when using composite JSF components & action methods never being called

I've been asked to refactor the following code, which works:
<a4j:commandButton type="image"
image="/someImage.gif"
action="#{SomeViewController.someDeleteAction}"
onclick="return confirm('#{msg['a.message']}');"
render="someDataTableWithItems">
<f:setPropertyActionListener
target="#{SomeViewModel.selectedItem}" value="#{item}" />
</a4j:commandButton>
..to an alternative which allowed to use a custom popup to confirm the action. This snippet is embedded into a column inside a rich:dataTable component. #{item} is a reference to the object assigned to the row where this button is (defined in the dataTable as var="item").
I decided to do a JSF composite component (first one I do) to have something I could reuse. It's based on this answer by elias
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:cc="http://java.sun.com/jsf/composite">
<cc:interface>
<cc:attribute name="message" default="#{msg['a.default.message']}" />
<cc:attribute name="header"
default="#{msg['a.default.header']}" />
<cc:attribute name="action" required="true"
method-signature="java.lang.String action()" />
<cc:attribute name="actionListener" required="false"
method-signature="java.lang.String action()" />
<cc:attribute name="value" default="Send" />
<cc:attribute name="cancelBtn" default="#{msg['a.default.cancel']}" />
<cc:attribute name="confirmBtn" default="#{msg['a.default.ok']}" />
<cc:attribute name="render" default="#form" />
<cc:attribute name="type" default="submit" />
<cc:attribute name="image" required="false"/>
<cc:attribute name="tooltip" required="false" />
</cc:interface>
<cc:implementation>
<a4j:commandButton type="#{cc.attrs.type}" rendered="#{empty cc.attrs.actionListener and not empty cc.attrs.image}"
image="#{cc.attrs.image}" value="#{cc.attrs.value}"
oncomplete="#{rich:component('somePopup')}.show()">
<rich:tooltip followMouse="false" showDelay="1000" rendered="#{not empty cc.attrs.tooltip}">
#{cc.attrs.tooltip}
</rich:tooltip>
</a4j:commandButton>
<a4j:commandButton type="#{cc.attrs.type}" rendered="#{not empty cc.attrs.actionListener and not empty cc.attrs.image}"
actionListener="#{cc.attrs.actionListener}"
image="#{cc.attrs.image}" value="#{cc.attrs.value}"
oncomplete="#{rich:component('somePopup')}.show()">
<rich:tooltip followMouse="false" showDelay="1000" rendered="#{not empty cc.attrs.tooltip}">
#{cc.attrs.tooltip}
</rich:tooltip>
</a4j:commandButton>
<a4j:commandButton type="#{cc.attrs.type}" rendered="#{empty cc.attrs.actionListener and empty cc.attrs.image}"
value="#{cc.attrs.value}"
oncomplete="#{rich:component('somePopup')}.show()">
<rich:tooltip followMouse="false" showDelay="1000" rendered="#{not empty cc.attrs.tooltip}">
#{cc.attrs.tooltip}
</rich:tooltip>
</a4j:commandButton>
<a4j:commandButton type="#{cc.attrs.type}" rendered="#{not empty cc.attrs.actionListener and empty cc.attrs.image}"
actionListener="#{cc.attrs.actionListener}" value="#{cc.attrs.value}"
oncomplete="#{rich:component('somePopup')}.show()">
<rich:tooltip followMouse="false" showDelay="1000" rendered="#{not empty cc.attrs.tooltip}">
#{cc.attrs.tooltip}
</rich:tooltip>
</a4j:commandButton>
<rich:popupPanel id="somePopup"
header="#{cc.attrs.header}" autosize="true" resizeable="false">
<p>#{cc.attrs.message}</p>
<a4j:commandButton action="#{SomeViewController.someDeleteAction}" <!-- It should be #{cc.attrs.action} but I just put this for debug -->
value="#{cc.attrs.confirmBtn}" render="#{cc.attrs.render}"
oncomplete="#{rich:component('somePopup')}.hide()">
<cc:insertChildren />
</a4j:commandButton>
<h:commandButton value="#{cc.attrs.cancelBtn}"
onclick="#{rich:component('somePopup')}.hide(); return false;" />
</rich:popupPanel>
</cc:implementation>
</html>
..and replace the previous a4j:commandButton with this:
<my:buttonConfirm type="image" id="someID"
image="/someImage.gif"
action="#{SomeViewController.someDeleteAction}"
message="#{msg['a.confirmation.message']}"
render="someDataTableWithItems"
tooltip="#{msg['a.tooltip.message']}">
<f:setPropertyActionListener for="someID"
target="#{SomeViewModel.selectedItem}" value="#{item}" />
</my:buttonConfirm>
The popup appears and you can cancel the action, but when confirming it, SomeViewModel is reinstantiated again, losing the previous bean in scope.
The scope is a custom view scope got from here
I then changed the scope of the model to this one:
#Component("SomeViewModel")
#ViewScoped
Although I tried to use #ManagedBean instead of #Component, the app gave me autowiring errors so I left #Component. The scope was now kept.
I don't know whether the mix of JSF and Spring annotations on this way may have any other consequences.
However the scope of SomeViewModel was now fine, the f:setPropertyActionListener target was never set and the action #{SomeViewController.someDeleteAction} was never called. I have been unable to debug this (not sure where to put breakpoints to see what happens in the middle).
Thanks in advance for your help.
The <f:setPropertyActionListener> does not attach to a component id, but to an ActionSource. See this answer for how to do it.
Edit:
Basically instead of <f:setPropertyActionListener for="buttonId"> you'll have
<cc:interface>
<cc:actionSource name="source" targets="buttonId" />
…
</cc:interface>
<cc:implementation>
<a4jcommandButton id="buttonId" … />
</cc:implementation>
And point to it by <f:setPropertyActionListener for="source">.
After trying some suggestions and researching a little on my own I concluded that there is some kind of problem when using a4j:commandButton inside a rich:popupPanel. Action methods are not being called and attributes defined on f:setPropertyActionListener are not being setted. I have been unable to find out what is exactly getting lost in there.
I've seen examples on the Internet with a4j:commandButton inside a popup so I am not sure if this is caused by any of my dependencies. I use jsf-api 2.1.19, jsf-impl 2.1.19-jbossorg-1 and richfaces 4.3.5.Final.
This is the workaround I finally did. I hope it can be helpful to anyone with the same problem I had:
confirmButton.xhtml
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:cc="http://java.sun.com/jsf/composite">
<cc:interface>
<cc:attribute name="message"
default="Some message" />
<cc:attribute name="header"
default="Some header" />
<cc:attribute name="cancelBtn" default="No" />
<cc:attribute name="confirmBtn" default="Yes" />
<cc:attribute name="type" default="submit" />
<cc:attribute name="icon" required="false" />
<cc:attribute name="image" required="false" />
<cc:attribute name="action"
targets="popupConfirmButton" />
<cc:actionSource name="confirmListeners"
targets="popupConfirmButton" />
</cc:interface>
<cc:implementation>
<a4j:commandButton type="#{cc.attrs.type}"
image="#{cc.attrs.image}"
oncomplete="#{rich:component('popupConfirm')}.show()">
</a4j:commandButton>
<a4j:commandButton id="popupConfirmButton"
style="visibility: hidden;" render="#{cc.attrs.render}">
</a4j:commandButton>
<rich:popupPanel id="popupConfirm" header="#{cc.attrs.header}"
autosized="true" width="475" resizeable="false">
<f:facet name="controls">
<h:outputLink value="#"
onclick="#{rich:component('popupConfirm')}.hide(); return false;" />
</f:facet>
<h:panelGrid columns="2">
<h:graphicImage value="#{cc.attrs.icon}" height="64" width="64" />
<p>#{cc.attrs.message}</p>
</h:panelGrid>
<br />
<div align="right">
<a4j:commandButton value="#{cc.attrs.confirmBtn}"
onclick="#{rich:element('popupConfirmButton')}.click();
#{rich:component('popupConfirm')}.hide();" />
 
<h:commandButton value="#{cc.attrs.cancelBtn}"
onclick="#{rich:component('popupConfirm')}.hide(); return false;" />
</div>
</rich:popupPanel>
</cc:implementation>
</html>
Component usage
<my:confirmButton type="image" image="someButtonImage.gif"
icon="someWarningImage.gif"
action="#{SomeViewController.doStuff}"
message="Some message"
render="someComponentID">
<f:setPropertyActionListener for="confirmListeners"
target="#{SomeViewModel.someProperty}" value="foo" />
</my:confirmButton>

AJAX within nested JSF Composite Component

I'm having a bit of trouble getting AJAX calls to fire properly in a nested composite component with Mojarra 2.0.3 and PrimeFaces.
The child composite component looks something like this:
<cc:interface componentType="therapy">
<cc:attribute name="therapyType" type="java.lang.String" required="true"/>
<cc:attribute name="patientId" type="java.lang.String" required="true"/>
<cc:attribute name="showHistory" type="java.lang.Boolean" required="false" default="true"/>
<cc:attribute name="width" type="java.lang.String" required="false" default="350px"/>
<cc:attribute name="maxHistory" type="java.lang.String" required="false" default="3"/>
<cc:attribute name="collectDoctor" type="java.lang.Boolean" required="false" default="false"/>
<cc:attribute name="collectCareDate" type="java.lang.Boolean" required="false" default="false"/>
<cc:attribute name="important" type="java.lang.Boolean" requred="false" default="false"/>
</cc:interface>
<cc:implementation>
<script>
function #{cc.clientId}Toggle(){
$("##{cc.clientId}_newbutton").toggle();
$("##{cc.clientId}_savebuttons").toggle();
if(#{cc.attrs.collectDoctor}){
$("##{cc.clientId}_doctor").toggle();
}
if(#{cc.attrs.collectCareDate}){
$("##{cc.clientId}_care").toggle();
}
$("##{cc.clientId}_newTherapy").toggle(50);
}
function #{cc.clientId}rowHighlight(event){
if(event.status == 'begin'){
$("##{cc.clientId}_loader").toggle();
}
if(event.status == 'success'){
$("##{cc.clientId}\\:histTable tr:eq(1)").effect("highlight", {color:"#FED17A", easing:"easeInCubic"}, 2000);
}
}
$(function(){
if(#{cc.attrs.important}){
$("div[class~='ui-panel-titlebar'][id^='#{cc.clientId}']").css("background", "#FED17A");
}
});
</script>
<h:form prependId="false">
<p:panel styleClass="mcoPanel" style="width:#{cc.attrs.width};">
<f:facet name="header">
<h:panelGroup>
<span id="#{cc.clientId}_title">#{cc.myType.word}</span>
<span id="#{cc.clientId}_newbutton" class="mcoPanel-controls">
<span onclick="#{cc.clientId}Toggle();">
<h:graphicImage name="page_new.gif" library="images"/>
</span>
</span>
<span id="#{cc.clientId}_savebuttons" class="mcoPanel-controls" style="display:none;">
<span id="#{cc.clientId}_loader" style="display:none;">
<h:graphicImage name="ajax-loader.gif" library="images" height="16" width="16"/>
</span>
<h:commandLink action="#{cc.saveNewTherapy}">
<f:ajax execute="newOnTherapy newExemption newDoctor newCareDate" render="#form" onevent="#{cc.clientId}rowHighlight"/>
<h:graphicImage name="action_save.gif" library="images"/>
</h:commandLink>
<span onclick="#{cc.clientId}Toggle();">
<h:graphicImage name="page_cross.gif" library="images"/>
</span>
</span>
</h:panelGroup>
</f:facet>
<div id="#{cc.clientId}_newTherapy" class="mcoPanel-new" style="display:none;">
<h:outputLabel for="newOnTherapy" value="Satisfied:" style="position:relative; top: -10px;"/>
<p:selectOneMenu id="newOnTherapy" label="Satisfied" value="#{cc.newOnTherapyValue}" style="width: 60px;">
<f:selectItem itemLabel=""/>
<f:selectItems value="#{cc.yesNoList}"/>
</p:selectOneMenu>
<br/>
<h:outputLabel for="newExemption" value="Exemption:" style="position:relative; top: -10px;"/>
<p:selectOneMenu id="newExemption" value="#{cc.newExemption}" style="width: 150px;">
<f:selectItems value="#{cc.exemptions}"/>
</p:selectOneMenu>
<span id="#{cc.clientId}_doctor" style="display:none">
<br/>
<h:outputLabel for="newDoctor" value="Doctor:"/>
<p:inputText id="newDoctor" value="#{cc.newDoctor}"/>
</span>
<span id="#{cc.clientId}_care" style="display:none">
<br/>
<h:outputLabel for="newCareDate" value="Care Date:"/>
<p:calendar id="newCareDate" label="Care Date" value="#{cc.newCareDate}" showButtonPanel="true">
<f:converter converterId="dateOfBirthConverter"/>
</p:calendar>
</span>
</div>
<h:messages id="#{cc.clientId}_messages" errorClass="errorMessage"/>
<p:dataTable id="histTable" value="#{cc.history}" var="item" rendered="#{cc.attrs.showHistory}">
<!-- Table Output -->
</p:dataTable>
</p:panel>
</h:form>
And the parent composite component looks something like this:
<cc:interface>
<cc:attribute name="title" type="java.lang.String" required="true"/>
</cc:interface>
<cc:implementation>
<h:outputScript name="containerpanel.js" library="js/components" target="head"/>
<p:panel toggleable="true" styleClass="contentPanel" toggleSpeed="500" style="width:1100px;">
<f:facet name="header">
#{cc.attrs.title}
<div class="ui-panel-titlebar-icon ui-corner-all ui-state-default contentSaveAll">
Save All
</div>
<div class="ui-panel-titlebar-icon ui-corner-all ui-state-default contentExpandAll">
++
</div>
<div class="ui-panel-titlebar-icon ui-corner-all ui-state-default contentCollapseAll">
- -
</div>
</f:facet>
<cc:insertChildren>
<!-- Child components go here -->
</cc:insertChildren>
</p:panel>
</cc:implementation>
The implementation is supposed to allow for any number of child components inside the container component.
The child components send ajax requests and update their internal components perfectly if they are placed on a page outside of the Container component. In addition, if I use the same structure of the container, but not an actual composite component, everything works just fine.
As soon as I place the child components as children of the Container component, that's where things go wonky. No ajax calls in the child components fire properly (i.e. the save commandLink) Using firebug to help debug this, I've been able to determine the following:
The ajax post request appears to be being sent. The "begin" onevent is firing, and looking at the console in firebug shows a post being made to the server, with the proper component ids and values being sent back.
The action in the backing bean is not being called. I have a print statement as the first line and it's not printing.
The ajax request appears to be completing properly, the "success" onevent is firing.
Nothing is being updated on the page. The form does not refresh, nor does the p:messages object at the top of the page.
Obviously I can do this without the Container component, but I would prefer to be able to of course take advantage of code reuse. Am I missing something obvious here that I need to do to get the ajax to work properly?
I am having the exact same problem with MyFaces 2.1.6.
I can't make AJAX calls from nested Composite Components using ClientBehavior in the interface of the CC.
Like moneyT wrote the server is being notified of the events specified in the ajax tag, but when the lifecycle went to phase 5 - Invoke Application, the event was null and no listener was called. More and more it looks like a bug in the implementation of MyFaces.
EDIT: I have found another solution which is much better than hardcoding ajax in the composite component. I have refactored the outer composite component to be facelet. It loses some of the quirks of the composites but it gets the job done. Also it is reusable.
The only solution (more of a workaraund than solution) I found is to hardcode ajax in the composite component rather than to use ClientBehavior, like this:
<composite:implementation>
<h:panelGroup layout="block" id="listBox" class="list-box-scroll-pane" style="height:#{cc.attrs.visibleLines*27 + 5}px; width:#{cc.attrs.width}px">
<h:inputText id="submit-value" style="visibility: hidden; width:0px; height: 0px;" value="#{cc.attrs.property}">
<f:ajax event="change"
render="carModel"
listener="#{carDetailsMediator.changeCarMake}"
onevent="initComboboxes"/>
</h:inputText>
<ui:repeat value="#{cc.attrs.items}" var="element" varStatus="loop">
<input id="input-#{cc.attrs.customId}-#{loop.index}" type="hidden"
value="#{element.value}" />
<div id="div-#{cc.attrs.customId}-#{loop.index}" class="list-box-row">#{element.label}</div>
</ui:repeat>
</h:panelGroup>
</composite:implementation>
However this workaround is not very good, because the idea behind composite components is that you can reuse them with many different options. Hardcoding ajax in it kind of limits the options.
I believe your problem is this:
<f:ajax execute="newOnTherapy newExemption newDoctor newCareDate" ...
The execute attribute can refer to the special keywords (Eg. #this, #form, etc...) or according to the documentation:
If a literal is specified, it must be a space-delimited String of component identifiers and/or one of the keywords.
When you are inserting this component as a child to the parent component then the component Ids are going to by dynamically determined and can't be referred to absolutely.

f:ajax works only with #form or #all

i have a composite component that contains a form with ajax. what i can't figure out is why it only works for the #form/#all render parameter.
<cc:interface>
<cc:attribute name="radioItem"/>
<cc:attribute name="radioItems" />
<cc:attribute name="compImage" />
<cc:attribute name="compSpecification"/>
</cc:interface>
<!-- IMPLEMENTATION -->
<cc:implementation>
<h:form>
<div id="options">
<h:selectOneRadio value="#{cc.attrs.radioItem}" >
<f:selectItems value="#{cc.attrs.radioItems}" />
<f:ajax render=":details" />
</h:selectOneRadio>
</div>
<div id="details">
<h:graphicImage value="#{cc.attrs.compImage}"/>
<h:outputText value="#{cc.attrs.compSpecification}"/>
</div>
</h:form>
</cc:implementation>
What am i missing?
This problem is two-fold:
You're specifying an absolute client ID :details while the element to be re-rendered is inside the same UINamingContainer parent, so JSF won't be able to locate it in the component tree. You need to specify a relative client ID details.
You have specified the ID on a plain vanilla HTML element instead of a real JSF component, so JSF won't be able to locate it in the component tree. You need to use a real JSF component. You need to replace <div> by <h:panelGroup layout="block">.
So, fix it both:
<h:form>
<div id="options">
<h:selectOneRadio value="#{cc.attrs.radioItem}" >
<f:selectItems value="#{cc.attrs.radioItems}" />
<f:ajax render="details" />
</h:selectOneRadio>
</div>
<h:panelGroup id="details" layout="block">
<h:graphicImage value="#{cc.attrs.compImage}"/>
<h:outputText value="#{cc.attrs.compSpecification}"/>
</h:panelGroup>
</h:form>
That it works with #form and #all is just because JSF can locate the element to be re-rendered relative to the component on which the ajax action is been invoked, namely the parent UIForm and UIViewRoot component respectively.

Resources