<f:ajax> doesn't work on PrimeFaces component - ajax

I trying to use the onChange event of selectOneMenu, but it doesn't work and the component is not displayed when I add onChange attribue.
Can someone tell me how can I handle the onChange event of <p:selectOneMenu>?
Here is my view:
<p:selectOneMenu id="service" filterMatchMode="startsWith">
<f:selectItem itemLabel="Selectionner un Service : " />
<f:selectItems value="#{newOpProgramme.listeSevice}" var="service" itemValue="#{service.serviceId}" itemLabel="#{service.serviceNom}"/>
<f:ajax event="change" execute="#this" listener="#{newOpProgramme.serviceChange()}" render="nomCdp"/>
</p:selectOneMenu>
And here is the <f:ajax listener> method in a request scoped bean:
public void serviceChange() {
System.out.println("change");
}
When I change the menu, however, nothing is been printed.
How is this caused and how can I solve it?

First of all, onChange is the wrong event name. It's change. Secondly, if you intend to call the HTML attribute name, onChange is also the wrong attribute name. It's onchange.
Coming back to your concrete problem; the standard JSF <f:ajax> is not compatible with PrimeFaces components. You should be using PrimeFaces own <p:ajax> instead.
<p:selectOneMenu ...>
...
<p:ajax listener="#{newOpProgramme.serviceChange()}" update="nomCdp" />
</p:selectOneMenu>
Note that I omitted the event and the process attributes. They both have already the right default value of valueChange and #this respectively.
See also:
What values can I pass to the event attribute of the f:ajax tag?
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes

When I want to update something after change in selectOneMenu, I use <f:ajax> tag inside selectOneMenu like this:
<h:selectOneMenu value="#{bean.selected}" >
... select items here
<f:ajax event="change" execute="#this" render="search" />
</h:selectOneMenu>
Where search is the Id of the object you want to update.
Other solution is that you should try onchange not onChange.

<p:selectOneMenu value="#{someBean.myAttr.id}" valueChangeListener="#someBean.mySelectioMethodListener}">
<f:selectItems value="#{someBean.listAttrs}" var="item"
itemLabel="#{item.name}" itemValue="#{item.id}" />
<p:ajax process="#this" update="someElementId" />
</p:selectOneMenu>
You must put an Id for <f:selectItems /> and set your selection on backing bean side by posted ajax itemValue (id).
Server side method bean without a converter:
public void mySelectionMethodListener(ValueChangeEvent event) {
ApplicationContext context = FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());
SomeBeanDao someBeanDao = (SomeBeanDao) context.getBean(SomeBeanDao.class);
myAttr = someBeanDao.byId((Long) event.getNewValue());
System.out.println("value changed...");
}

Related

How to conditionally run jsf Validator on blur event with p:ajax?

In my xhtml page I have inputText field with two Validators attached to it. Also there is ajax event "blur" attached for triggering validation when switching focus from a field. Here is the code:
<t:selectOneMenu id="locateRecordBy" value="#{personBean.locateRecordBy}">
<f:selectItems value="#{personBean.locateRecordByItems}"/>
</t:selectOneMenu>
<t:inputText id="personName"
value="#{personBean.name}"
required="true"
requiredMessage="Name is required.">
<p:ajax event="blur" partialSubmit="true" process="#this" update="nameerror" global="false" />
<f:validator disabled="#{param['PersonForm:locateRecordBy'] == 'FEMALE'}" validatorId="com.myapp.validators.MalePersonValidator"/>
<f:validator disabled="#{param['PersonForm:locateRecordBy'] == 'MALE'}" validatorId="com.myapp.validators.FemalePersonValidator"/>
</t:inputText>
So I'd like to validate personName against appropriate Validator depending of selecting item after focus is not anymore on the personName field. Any suggestions please, what should I change or add?
p.s. On form submit validation work very well.
Actually I found what was missing in my code. I added locateRecordBy componnent to be processed with ajax so instead of having this:
<p:ajax event="blur" partialSubmit="true" process="#this" update="nameerror" global="false" />
I have this:
<p:ajax event="blur" partialSubmit="true" process="#this, locateRecordBy" update="nameerror" global="false" />
Basically I forgot instruct JSF to process locateRecordBy and that's why locateRecordBy parameter was never present in the ajax request which caused both validators to be became disabled and validation of personName field to be skipped.

p:ajax update not working with p:selectBooleanCheckbox

I'm using JSF 2 and Primefaces 4 and have the following issue:
I've got the following code in my XHTML:
<h:form id="form">
<table>
<tr id="formats">
<td>Formats</td>
<td>
<p:selectBooleanCheckbox value="#{bean.entity.formatted}">
<p:ajax event="change" update="formatsSelect" />
</p:selectBooleanCheckbox>
<p:selectOneMenu id="formatsSelect" rendered="#{bean.entity.formatted}">
<f:selectItems value="#{bean.formats}" />
</p:selectOneMenu>
</td>
</tr>
</table>
</h:form>
It outputs a checkbox and a select menu and what I expect is that when I check the checkbox the select menu should appear and should disappear when I uncheck it.... but nothing happens, I check and uncheck it and the select menu is unaffected.
In theory this should work since the selectBooleanCheckbox value is bound to the entity.formatted boolean value and the rendered value in the selectOneMenu is bound to the entity.formatted value and the p:ajax points to the correct id in the update attribute and the event is correct. This last bit I know since I created a listener in my bean that printed the value of formatted:
public void changeListener(){
System.out.println(this.entity.isFormatted());
}
And changed the p:ajax to:
<p:ajax event="change" update="formatsSelect" listener="#{bean.changeListener}" />
And it printed the value of formatted in the console.
What am I doing wrong?
Since you used rendered on the component (p:selectOneMenu id="formatsSelect") and updating the same component, it wont work.
Because that component might not have been added to/present in component tree by the time you are updating.
So use a h:panelGroup around it and update it and use rendered on p:selectOneMenu.
<p:selectBooleanCheckbox value="#{bean.entity.formatted}">
<p:ajax event="change" update="formatsSelectPG" />
</p:selectBooleanCheckbox>
<h:panelGroup id="formatsSelectPG">
<p:selectOneMenu id="formatsSelect" rendered="#{bean.entity.formatted}">
<f:selectItems value="#{bean.formats}" />
</p:selectOneMenu>
</h:panelGroup>

h:panelGroup not rendered when change the value of h:selectOneMenu using AJAX

I have a grid group that should be rendered when change the value of the selectOneMenu. I have attached a valueChangeListener to the selectOneMenu and it access succefully the function assigned to it , but the html component does not rerender. the strange thing that the flag the determines the rendering is called anyway.
<h:selectOneMenu value="#{channelsAdmin.profileID}" id="profileDrp" valueChangeListener="#{channelsAdmin.setProfileInit}">
<f:selectItems value="#{channelsAdmin.profiles}" var="Profile"
itemLabel="#{Profile.profileName}"
itemValue="#{Profile.profileId}" />
<f:ajax execute="#this" immediate="true" render="pnl"></f:ajax>
</h:selectOneMenu>
<h:panelGroup id="pnl" rendered="#{channelsAdmin.ccpAuthPanelFlage}">
<h:inputText id="sest" value="hew">
</h:inputText>
</h:panelGroup>
Bean:
public void setProfileInit(ValueChangeEvent e) {
ccpAuthPanelFlage=true;
ccpPurchPanelFlage=true;
}
The <f:ajax render="pnl"> works roughly as follows:
When the ajax response is arrived, obtain the update element with id="pnl" from XML response.
Now obtain the element with id="pnl" from HTML document by document.getElementById().
Replace its contents with the update element from XML response.
In your particular case, step 2 failed because there's no such element in the HTML document. It doesn't exist in the HTML document because it's never been rendered in first place.
You need to make sure that <f:ajax render="..."> refers an element which is always rendered so that JavaScript can find it by document.getElementById() in order to replace its contents.
<h:selectOneMenu value="#{channelsAdmin.profileID}" id="profileDrp" valueChangeListener="#{channelsAdmin.setProfileInit}">
<f:selectItems value="#{channelsAdmin.profiles}" var="Profile"
itemLabel="#{Profile.profileName}"
itemValue="#{Profile.profileId}" />
<f:ajax execute="#this" immediate="true" render="pnl"></f:ajax>
</h:selectOneMenu>
<h:panelGroup id="pnl">
<h:panelGroup rendered="#{channelsAdmin.ccpAuthPanelFlage}">
<h:inputText id="sest" value="hew">
</h:inputText>
</h:panelGroup>
</h:panelGroup>
See also:
Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?

JSF2: cannot get data from a HtmlSelectOneMenu in java code

I am working with MyFaces/Primefaces and I have a problem to get information using ajax.
My page contains a list of panel, inside each panel, the user can select value in a dropdown list, and click on a checkbox which will update its panel (Ajax), I hope I am clear.
This is my code:
<p:panel>
...
<h:selectOneMenu id="beanSet" value="#{myBean.selectedSet}">
<f:selectItem itemLabel=" " noSelectionOption="true" />
<f:selectItems value="#{langSet}" />
</h:selectOneMenu>
<h:selectBooleanCheckbox
id="chkbxBeanSet"
value="#{myBean.selectedSetChkbx}" >
<p:ajax
event="click" render="#parent"
listener="#{action.updateSet}"
execute="#form"
immediate="true"
/>
</h:selectBooleanCheckbox>
...
<p:panel>
And here my java code:
public void updateSet(AjaxBehaviorEvent e) {
UIComponent source = (UIComponent)e.getSource();
System.out.println("Value:"+((HtmlSelectBooleanCheckbox)source).getValue());
UIComponent parent = source.getParent();
List<UIComponent> children = parent.getChildren();
HtmlSelectOneMenu lvSet = (HtmlSelectOneMenu)parent.findComponent("beanSet");
Object value = lvSet.getValue();
System.out.println("value: " + value);
I get the beanSet component, but I can't get its value. As I understand, the getValue calls the getSelectedSet from myBean which is not set (it is in request scope).
I don't understant how I can get the selected value in the dropdown list using ajax.
Another way is to post all the form, but in that case, I have to determine which checkbox was clicked by the user...
If someone can explain me where I am wrong?
The culprit is immediate="true" on the ajax action. This will skip all input components which do not have this attribute set during the processing. You should finetune the to-be-processed components in the process attribute of <p:ajax>. Yes, another culprit is that you used execute instead of process. The <p:ajax> uses process where <f:ajax> uses execute. Also, the way how you accessed the dropdown value is unnecessarily overcomplicated. Just access the selectedSet property directly. JSF will set it in the same bean anyway.
So, this should do
<h:selectOneMenu id="beanSet" value="#{myBean.selectedSet}">
<f:selectItem itemLabel=" " noSelectionOption="true" />
<f:selectItems value="#{langSet}" />
</h:selectOneMenu>
<h:selectBooleanCheckbox id="chkbxBeanSet" value="#{myBean.selectedSetChkbx}">
<p:ajax process="#this beanSet" listener="#{action.updateSet}" update="#parent" />
</h:selectBooleanCheckbox>
with
public void updateSet() {
System.out.println(selectedSet);
}
Note that I omitted event="click" from <p:ajax>. It's already the default for checkboxes.
place this (listener is optional) , the <f:ajax event="change" is what you need the most
<f:ajax event="change" render="IdsOfComponentToRender" listener="#{myBean.someMethod}" />
inside your <h:selectOneMenu id="beanSet" value="#{myBean.selectedSet}">
this is the signature of the listener
public void someMethod(AjaxBehaviorEvent ev) {...
b.t.w what is that updateLvSet method , and where you call it , and you should not access you data that way...

How to save 2 dependent selectOneMenu values

I'm running in a little issue here regarding jsf related dropdown selection.
I have 2 dropdown selection: the first one is independent, the second one shows result depending from This is the code:
<h:panelGroup id="addressPanel">
<h:outputLabel styleClass="label" value="Provincia: " />
<h:selectOneMenu onchange="updateCombos()"
value="#{indirizzoCtrl.codiceProvincia}" >
<f:selectItem itemValue="" itemLabel=""></f:selectItem>
<f:selectItems value="#{indirizzoCtrl.allProvincia}" var="c"
itemLabel="#{c.nome}" itemValue="#{c.siglaProvincia}" />
</h:selectOneMenu>
<h:outputLabel styleClass="label" value="Comune: " />
<h:selectOneMenu
value="#{indirizzoCtrl.codiceComune}" >
<f:selectItem itemValue="" itemLabel=""></f:selectItem>
<f:selectItems value="#{indirizzoCtrl.allComuni}" var="c"
itemLabel="#{c.descrizione}" itemValue="#{c.codiceComune}" />
</h:selectOneMenu>
</h:panelGrid>
</h:panelGroup>
<p:remoteCommand name="updateCombos" update="addressPanel masterForm:msg" />
<p:commandButton styleClass="commandButton" value="Save"
actionListener="#{indirizzoCtrl.save}">
</p:commandButton>
Well, when the user save the form after selecting both the value, the managed bean indirizzoCtrl (request scoped) cannot map the value of the second dropdown back to the list, because there's no list.
In fact the #{indirizzoCtrl.allComuni} call a getter that retrieve the data from the DB only if indirizzoCtrl.codiceProvincia!=null... and that's false before the update model phase.
So the first time the getter for the list is called cannot retrieve any values, and that's bring the update model phase to fail.
How can I handle this scenario... I think it's a pretty common one, so I'm missing something here...
Put the bean in the view scope instead. It will live as long as you're interacting with the same view by ajax. A request scoped bean get indeed recreated on every single request, also ajax requests, so bean properties would reinitialize to their defaults.
#ManagedBean
#ViewScoped
public class IndidizzoCtrl implements Serializable {
// ...
}
See also:
How to load and display dependent h:selectOneMenu on change of a h:selectOneMenu
How to choose the right bean scope?
Unrelated to the concrete problem, I also strongly recommend to change your getter methods to not do any business job, but just return data. Do the business job in (action)listener methods instead. E.g.
<h:selectOneMenu value="#{bean.menu1item}">
<f:selectItems value="#{bean.menu1items}" />
<f:ajax listener="#{bean.updateMenu2}" render="menu2" />
</h:selectOneMenu>
<h:selectOneMenu id="menu2" value="#{bean.menu2item}">
<f:selectItems value="#{bean.menu2items}" />
</h:selectOneMenu>
with
public void updateMenu2() {
menu2items = loadItBasedOn(menu1item);
}
See also:
Why JSF calls getters multiple times

Resources