How to save 2 dependent selectOneMenu values - ajax

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

Related

primefaces dont validate ajax rendered component

<h:form id="formEdit">
<p:selectOneMenu value="#{testView.selection}"
required="true">
<f:selectItem itemValue="noMenu" itemLabel="selectOneMenu not rendered"/>
<f:selectItem itemValue="haveMenu" itemLabel="selectOneMenu rendered"/>
<p:ajax update="formEdit"/>
</p:selectOneMenu>
<p:panel>
<p:selectOneMenu id="conditionallyRnedered" value="#{testView.value}"
rendered="#{testView.selection eq 'haveMenu'}"
required="true">
<f:selectItem itemValue="#{null}" itemLabel="-" noSelectionOption="true"/>
</p:selectOneMenu>
</p:panel>
<p:messages id="messages"/>
<p:commandButton value="Submit"/>
</h:form>
Component "conditionallyRnedered" is required, and rendered on page after i select "haveMenu" value in first menu. This component have only empty option and initialy its not rendered on page. If i press Submit button, then response is:
<partial-response><changes>
<update id="javax.faces.ViewState"><![CDATA[stateless]]></update>
</changes></partial-response>
There is no validation error. If i change value of rendered attribute in "conditionallyRnedered" from "#{testView.selection eq 'haveMenu'}" to just "true", then response is:
<partial-response><changes>
<update id="javax.faces.ViewState"><![CDATA[stateless]]></update>
<extension ln="primefaces" type="args">{"validationFailed":true}</extension></changes>
</partial-response>
Validation error returned. The questions is:
Why conditionally rendered component is not validated?
It is possible to make them validated?
UPD
Originally in my question is absent Bean source code, in which Bean declared as #ViewScoped. After read #BalusC comment, i try to change scope from #ViewScoped to #SessionScoped, and after that validation is working correctly. Wherein javax.faces.ViewState in response changed from stateless to some view id:
<update id="javax.faces.ViewState">-5902669082498843838:729675320168079573</update>
I still doubt, this is solution or still workaround, because I thought that instance of #ViewScoped bean is exist while we dont left the page. Maybe this behavior is caused by the fact that in the same page present another bean, with #SessionScoped scope.
It failed for the technical reason explained in this Q&A: Form submit in conditionally rendered component is not processed. In a nutshell, JSF will re-check the rendered attribute during processing the form submit/conversion/validation and skip components which aren't rendered during that moment. The answer is to use a #ViewScoped bean.
That it still failed in spite of that you're actually using a #ViewScoped bean is because you're using a stateless view via <f:view transient="true">, as confirmed by the actual javax.faces.ViewState value and What is the usefulness of statelessness in JSF? In other words, JSF won't save/restore the view, including any view scoped beans. Those beans will technically behave like #RequestScoped beans and thus be recreated on every request, resetting their properties to defaults everytime.
To solve your problem, just turn off stateless view by removing <f:view transient="true"> and keep your bean #ViewScoped.
#bobzer,
primefaces commandButton has become ajax="true" by default. So when i set ajax="false", the form is submitted and i can see validation errors
i get
My xhtml:
<h:form id="formEdit">
<p:selectOneMenu value="#{testView.selection}" required="true">
<f:selectItem itemValue="noMenu"
itemLabel="selectOneMenu not rendered" />
<f:selectItem itemValue="haveMenu" itemLabel="selectOneMenu rendered" />
<p:ajax update="formEdit" />
</p:selectOneMenu>
<p:panel>
<p:selectOneMenu id="conditionallyRnedered" value="#{testView.value}"
rendered="#{testView.selection eq 'haveMenu'}" required="true">
<f:selectItem itemValue="#{null}" itemLabel="-"
noSelectionOption="true" />
</p:selectOneMenu>
</p:panel>
<p:messages id="messages" />
<p:commandButton value="Submit" ajax="false"/>
</h:form>
My Bean
package citi.manageID.framework.admin.roleMgmt;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
#Named
#ViewScoped
public class TestView {
private String selection="";
private String value="";
public String getSelection() {
return selection;
}
public void setSelection(String selection) {
this.selection = selection;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

Why are fields reset after ajax update with Primefaces

On a form I have some personal information (name, address etc.) and a changeListener which updates the salutation and letter salutation according to the gender and last name. If the underlying entity was already stored in the database it works fine. If I'm entering data for a new (not saved) entry the form gets reset after the listener has been called. All data entered is lost, only the salutation, lettersalutation which I modify in the listener and gender, name which I use and attached a ajax call on are kept.
This is a part of the form:
<h:form id="person">
<p:panel header="#{msg['prs']}">
<h:panelGrid columns="6" cellpadding="4">
<h:outputText value="#{msg['prs.salutation']}"/>
<p:inputText value="#{personBean.selectedPerson.salutation}"/>
<h:outputText value="#{msg['prs.lettersalutation']}"/>
<p:inputText value="#{personBean.selectedPerson.letterSalutation}"/>
<p:spacer/><p:spacer/>
<h:outputText value="#{msg['prs.name']}: "/>
<p:inputText value="#{personBean.selectedPerson.name}">
<p:ajax event="change" update="person"
listener="#{personBean.selectedPerson.updateSalutation}" />
</p:inputText>
<h:outputText value="#{msg['prs.surname']}: "/>
<p:inputText value="#{personBean.selectedPerson.surname}"/>
<h:outputText value="#{msg['prs.gender']}: "/>
<p:selectOneMenu value="#{personBean.selectedPerson.gender}">
<f:selectItems value="#{enumHelper.getEnum('Gender')}"/>
<p:ajax event="change" update="person"
listener="#{personBean.selectedPerson.updateSalutation}" />
</p:selectOneMenu>
</p:panel>
</h:form>
In the code I do then the updates.
public void updateSalutation() {
// simplified
letterSalutation = "...";
salutation = "...";
// outputs for debug
System.out.println(this.getName()); // --> not null
System.out.println(this.getSurname()); // --> null
}
Already here in this call surname, which is not attached to a ajax call is null even though data was entered there. The same is true for all the other fields. In my application I'm using Primefaces, JavaEE 1.6 with Wildfly.
What is the reason for that behavior? Is there anything I can change on my calls to prevent this?
Why are fields reset after ajax update with Primefaces
This problem has 2 possible causes depending on the concrete functional requirement:
It's because you didn't tell JSF to process the desired input values.
Or, it's because you told JSF to also update the non-desired input values.
The solution depends on the cause:
Add process="person" (or process="#form") to <p:ajax> to process the whole form.
Or, edit update="person" to specify only the components which really need to be updated.
Given your complaint in the end of the question, I believe you're looking for #1.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
My solution:
Include the content that I want to update in a
<p:panel id="toUpdate">
and make a
update="toUpdate"

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

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...");
}

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...

Primefaces dropdown not setting value

I am trying to delete an image which belongs to an album.
I provide 2 drop downs, the first allows to select the album the second to select an image of the album. The first when changes sets the second.
Then the remove button calls a remove method.
I have debugged it a number of times but the values are always null.
Do you know why? how can I make it work?
note: when I set the first drop down the value is present but after I set the second they both become null.
Thanks
<h:form>
<h:panelGrid>
<h:outputLabel value="#{diaryMB.selectedAlbum}"/>
<p:selectOneMenu
id="albums" value="#{diaryMB.selectedAlbum}" effect="drop">
<f:selectItem itemLabel="Select An Album" itemValue="-1" />
<f:selectItems value="#{diaryMB.albums}" var="album"
itemLabel="#{album}" itemValue="#{album}" />
<p:ajax event="change" listener="#{diaryMB.updateImage()}" update="images"/>
</p:selectOneMenu>
<h:outputLabel value="#{diaryMB.selectedImage}" />
<p:selectOneMenu
id="images" value="#{diaryMB.selectedImage}" effect="drop">
<f:selectItem itemLabel="Select An Image" itemValue="-1" />
<f:selectItems value="#{diaryMB.images}" var="image"
itemLabel="#{image}" itemValue="#{image}" />
</p:selectOneMenu>
<p:commandButton id="removeImageButton" value="Remove" ajax="false" action="#{diaryMB.removeImage()}"/>
</h:panelGrid>
</h:form>
public String removeImage(){
System.out.println("I am selected image:"+selectedImage);
System.out.println("I am slected album "+selectedAlbum);
if(selectedImage!=null && !selectedImage.equals("-1"))
{diaryManager.removeImageFromAlbum(diaryOwner, selectedAlbum, selectedImage);
return "Friends";}
else
return "Home";
}
It might be beacuase your managed bean is RequestScoped and is being recreated after every ajax request. Try using ViewScoped or SessionScoped and see if the values remain.

Resources