a4j:ajax not working with h:selectBooleanCheckbox - jsf-2

We are migrating from jsf 1.2 to jsf 2 and use following components.
Apache myFaces 2.2.12
Rich Faces 4.3.4
I am facing an issue while replacing <a4j:support> with <a4j:ajax> for <h:selectBooleanCheckbox>
Following is the xhtml code.
<h:panelGrid id="info" columns="2">
<c:forEach items="#{bean.list}" var="provider">
<h:selectBooleanCheckbox id="#{provider.name}" value="#{provider.select}"
disabled="false">
<a4j:ajax event="change" listener="#{bean.processProvider}" execute="#this" render="info">
<f:param name="name" value="#{provider.name}"/>
</a4j:ajax>
</h:selectBooleanCheckbox>
<h:outputText value="prod1"/>
</c:forEach>
<h:panelGrid>
On checking the selectBooleanCheckbox , listener is not getting called. I have tried following things :
1)Change listener method argument from ActionEvent to AjaxBehaviorEvent.
2)Change listener method to accept no argument.
3)a4j:ajax events tried - change,click,valueChange
Following is the method signature for listener method.
public void processProvider(AjaxBehaviorEvent event){
}
Nothing seems to be working .
Can anyone pleas help ?

Related

Passing parameter to a4j:ajax

We are upgrading from jsf 1.2 to jsf 2.
We are using apache myfaces 2.1 and rich faces 4.3.
Below is the xhtml code :
Prior to Migration :
<h:selectBooleanCheckbox id="comp1" value="#{bean.select}">
<a4j:support event="onclick" ajaxSingle="true" actionListener="#{bean.processInput}" reRender="compId">
<f:param name="name" value="paramValue"/>
</a4j:support>
</h:selectBooleanCheckbox>
We are passing one parameter with and accept the parameter in actionListener method as : (String)context.getExternalContext().getRequestParameterMap().get("name1");
After Migration :
<h:selectBooleanCheckbox id="comp1" value="#{bean.select}">
<a4j:ajax event="click" listener="#{bean.processInput}" execute="#this" render="compId"/>
</h:selectBooleanCheckbox>
I want to pass a parameter to bean.processInput method which has following signature :
public void processInput(AjaxBehaviorEvent event){
According to this post - Issues in passing parameter in f:ajax , we cannot use <f:param> (its not working
also) and we are not using EL 2.2 which rules out passing parameter in method signature.
Since we cannot use context.getApplication().evaluateExpressionGet due to constraints in our xhtml page only option available is
use <a4j:param name="" value="" assignTo=""/>.
But this needs to have one variable defined in bean requiring code change.
So my question is can we pass a parameter from UI to listener in second case and without changing the code.
You can use f:attribute like this :
<h:selectBooleanCheckbox id="comp1" value="#{bean.select}">
<a4j:ajax event="click" listener="#{bean.processInput}" execute="#this" render="compId"/>
<f:attribute name="name" value="paramValue" />
</h:selectBooleanCheckbox>
And use it in your bean :
public void processInput(AjaxBehaviorEvent event)
{
System.out.println(event.getComponent().getAttributes().get("name"));
}
Make sure that f:attribute component is not a child component of a4j:ajax.
it should be immediate child component of h:selectBooleanCheckBox, if not listener wont trigger.

ignoreValidationFailed doesn´t work inside ui:repeat

I´m using o:ignoreValidationFailed, but it doesn´t work inside the ui:repeat. When I do the same outside, it works! I tried with mojarra ans MyFaces... I´m using primefaces. If there is another way to skip the validations only for one button...
<o:form id="rateplanEditByPeriod" prependId="false">
<p><p:messages id="mensagensDlg"/></p>
<p:tabView id="tabs">
<p:tab title="Cancelamento" id="tabCanc">
<h:panelGrid id="cancelationsTable" columns="2" cellpadding="10px" columnClasses="alignTop,alignTop">
<ui:repeat id="repeat" var="rest" value="#{rateplanByPeriodManaged.rateplanByPeriod.restriction.restTypeCancelation.restTypeCanConfs}" >
<h:panelGrid columns="8">
<p:inputText id="penaltyValue_#{loop.index}" value="#{rest.penalityValue}" style="width:28px" label="Valor" title="Valor" disabled="#{rest.noCancel}" required="true"/>
<p:commandLink id="add_#{loop.index}" actionListener="#{rateplanByPeriodManaged.addCancConf}" update=":rateplanEditByPeriod:tabs:cancelationsTable" partialSubmit="true" process=":rateplanEditByPeriod:tabs:cancelationsTable" value="+">
<o:ignoreValidationFailed />
</p:commandLink>
<p:commandLink actionListener="#{rateplanByPeriodManaged.removeCancConf(rest)}" value="-" update=":rateplanEditByPeriod:tabs:cancelationsTable" partialSubmit="true" process=":rateplanEditByPeriod:tabs:cancelationsTable">
<o:ignoreValidationFailed />
</p:commandLink>
</h:panelGrid>
</ui:repeat>
</h:panelGrid>
</p:tab>
</p:tabView>
<p:commandLink styleClass="button" onclick="dlgEdit.hide()" immediate="true" update=":msgsPanel">#{msgs['inventory.editByPeriod.cancel']}</p:commandLink>
<p:commandLink styleClass="button" actionListener="#{rateplanByPeriodManaged.editByPeriod(loginManaged.hotelSelected)}" oncomplete="if (!args.validationFailed) {dlgEdit.hide(); updateAllSearches(); updateAllNotifications();}" update="mensagensDlg, tabs" >#{msgs['inventory.editByPeriod.confirm']}</p:commandLink>
</o:form>
I have faced the same issue but with p:datatable
I solved it with
1- add a condition to the required field to know if the ajax come from submit button or not
as #Camilla said.
required="#{!empty param['trans_desc_form:savetransid']}"/>
trans_desc_form is the entire form id and savetransid is the submit button save id
2- I removed #NotNull from my JPA entity which force the validation
#JoinColumn(name = "ITEMNO", referencedColumnName = "ITEMNO")
#ManyToOne(optional = false, fetch = FetchType.LAZY)
//#NotNull
private Item item;
I have created a question for this issue
ignoreValidationFailed doesn´t work inside p:dataTable
I don´t know if it´s the best aproach but it worked for me...
<h: inputText id="text1" value="" required="#{!empty param['formName:btnSave']}" />
This is not the right way to have a "Cancel" button.
Just put process="#this" in the <p:commandLink>, or if you don't need to do any business logic, make it a normal <h:link> which reloads the page (and thus implicitly recreates the request/view scoped bean).
As to <o:ignoreValidationFailed> the failure in <ui:repeat> on its own, please create an issue.

Constructor of a viewScoped class invoked twice

I've been struggling with this for two days with no success and I think it's already time to ask for your help. But first of all, this is what I'm using:
JSF 2 Mojara 2.1.1
Primefaces 3.4.2
Netbeans 7.1.1
Tomcat 7.0.37
And now, the problem: I have a main page which is composed by several other pages using several <ui:include .. /> tags, like this:
<ui:composition template="/resources/templates/template1.xhtml">
<ui:define name="appData">
<p:panelGrid columns="1" id="contenidoAplicacion" styleClass="noborder">
<h:form id="fNewPerson">
<p:panel header="New employee" style="min-height:40em">
<ui:include src="./forms/personal.xhtml" />
<p:accordionPanel styleClass="noborder" activeIndex="3">
<p:tab id="tabSomeData" title="Identidad profesional" >
<ui:include src="./forms/formSomeData.xhtml" />
</p:tab>
....
....
</ui:define>
</ui:composition>
The personal.xhtm file looks like this:
<p:panelGrid>
<p:row>
<p:column >
<h:outputLabel value="Field1"/>
<p:inputText label="Field1" id="field1" value="#{dataBacking.selectedPerson.field1}" tabindex="1"
required="true" size="10" >
<f:convertNumber for="field1" integerOnly="true" groupingUsed="false"/>
</p:inputText>
<p:inputText id="field2" value="#{dataBacking.selectedPerson.field2}" tabindex="2" required="true" size="1" maxlength="1" >
<p:ajax event="keyup" listener="#{dataBacking.check}"
process="field1 field2" partialSubmit="true"
update="field1 field2 photo"/>
</p:inputText>
</p:column>
<p:column rowspan="5" >
<p:graphicImage id="photo" value="#{dataBacking.selectedPerson.photo}" width="90" />
</p:column>
</p:row>
...
</p:panelGrid>
The check() method in the dataBacking class is irrelevant because it only checks if the field1 and the field2 meet some rules and it works properly. The problem comes when the main page is loaded for the first time. In that case, the <p:ajax /> component in personal.xhtml doesn't work. I have to reload the page (simply by pressing the F5 key) and this time it works as it would be expected.
I've been changing some attributes of the component, but nothing seems to work. I really don't know what else to do. Any kind of help will be apreciated.
EDITED. After one more day, I think the problem has nothing to do with Primefaces ajax component, as the title of the question suggested. I've come to this conclusion through these two facts:
The behaviour with the <f:ajax .../> component remains the same.
I've figured out that the view relative to the first time I load the page is not persisted. I'll try to explain myself.
The DataBacking class has defined its scope as view so that the page can "see" all the attributes and methods during the time it's been shown to the user. However, I've noticed that the constructor is called twice: the first time the page is loaded (and then, none of the methods of the class are successfully invoked) and when I refresh the page. In this last case, the behaviour of both the page and the class is the expected one.

f:param is not working with h:graphicImage

I'm getting <f:param> i.e., menuItemIndex value as null during my ajax call. Is it because it is with in <h:graphicImage> ??? Can any one suggest please? Note: Parameter is getting passed if I use <h:commandLink> instead of <h:graphicImage>.
<c:forEach items="#{cc.attrs.value}" var="menuItem" varStatus="loopItem">
....
<ui:fragment rendered="#{menuItem.hasChildren}">
<h:graphicImage library="images" name="#{menuItem.symbol}">
<f:ajax render=":fatcaForm:myMenu:menuID" event="click" listener="#{menuBean.refreshMenu}" />
<f:param name="menuItemIndex" value="{loopItem.count}" />
</h:graphicImage>
</ui:fragment>
....
</c:forEach>
The <h:graphicImage> is not a command component and it does therefore not support <f:param> children at all. The <f:param> works only when nested in an UICommand component, such as <h:commandLink> as you found out yourself.
So, this should do:
<h:commandLink action="#{menuBean.refreshMenu}">
<h:graphicImage library="images" name="#{menuItem.symbol}" />
<f:ajax render=":fatcaForm:myMenu:menuID" />
<f:param name="menuItemIndex" value="#{loopItem.count}" />
</h:commandLink>
(note that I fixed the EL syntax error in the <f:param value> as well)
Unrelated to the concrete problem, how you used the <h:graphicImage library> is not entirely right. Please carefully read What is the JSF resource library for and how should it be used?

p:selectOneMenu first ajax request issue

I have a problem with PrimeFaces p:selectOneMenu component when I try to update a p:dataGrid by changing the SelectOneMenu's value.
Xhtml:
<p:selectOneMenu value="#{bussinessOwnersViewerMB.selectedCity}" effect="explode">
<f:selectItems value="#{bussinessOwnersViewerMB.cities}" var="city" itemLabel="#{city.cityName}" itemValue="#{city.cityId}"/>
<p:ajax listener="#{bussinessOwnersViewerMB.handleCityChange}" update="mainform:bolist"/>
</p:selectOneMenu>
<p:dataGrid id="bolist" var="bo" value="#{bussinessOwnersViewerMB.bOwners}" columns="3" rows="#{bussinessOwnersViewerMB.os}">
<p:column>
<p:panel header="#{bo.bOName}">
<h:panelGrid columns="1">
<p:graphicImage value="/resources/images/#{bo.boType}/#{bo.bOId}/mainProfile.jpg"/>
</h:panelGrid>
</p:panel>
</p:column>
</p:dataGrid>
The problem is, when I change the selectOneMenu's value at the first time the datagrid doesn't get updated. What happen is only the postconstructor method is called, after the first change it works fine.
My managed bean is a viewscoped managed bean.
The listener method "bussinessOwnersViewerMB.handleCityChange" is :
public void handleCityChange(ValueChangeEvent event) {
bOwners = bovb.loadAllDistributerByType(new Integer(selectedCity)); // selectedcity is the selected item id
os = Integer.toString(bOwners.size());
}
In the past you couldn't update a dataGrid like that; you had to wrap it in a panelGroup. I don't know wether or not that has changed, but I still do it like that and it still works. So just put your dataGrid inside a panelGroup and update the panelGroup (instead of the dataGrid) in your ajax tag.
In my case the problem was generated by a <p:panel> that contains a <h:panelGroup>, so the partial submit using <p:ajax> did not work. This problem happen when in the form there are empty fields which has required=true.
I updated the <p:panel> in <h:panelGroup>.
From:
<p:panel ... >
...
<h:panelGroup ...>
<!-- Form inside -->
</h:panelGroup>
...
</p:panel>
to
<h:panelGroup ... >
...
<h:panelGroup ...>
<!-- Form inside -->
</h:panelGroup>
...
</h:panelGroup>

Resources