primefaces dont validate ajax rendered component - ajax

<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;
}
}

Related

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

JavaServer Faces ajax control not updating (enabling / disabling)

here is a snippet from my JSF page:
<p:selectBooleanCheckbox value="#{FormXYZ_01.propertyNone0}">
<p:ajax event="blur" render="propertyNone0" />
</p:selectBooleanCheckbox>
<p:inputTextarea id="propertyNone0" disabled="#{FormXYZ.propertyNone0}" rows="3" styleClass="fixed400" />
Here is the relevant code from my backing bean:
#ManagedBean(name="FormXYZ_01")
#SessionScoped
public class FormXYZ_01 implements Serializable {
private Boolean propertyNone0;
public Boolean getPropertyNone0() {return propertyNone0;}
public void setPropertyNone0(Boolean propertyNone0) {this.propertyNone0 = propertyNone0;}
My ultimate goal is for the textbox to disable when the selectBooleanCheckbox is checked. I am very new to JSF and am using primefaces.
Thanks!
Here is the code that ended up working:
<h:form>
<p:selectBooleanCheckbox value="#{FormXYZ_01.propertyNone0}">
<p:ajax event="change" update="ctrlPropertyDescLoc0" />
</p:selectBooleanCheckbox>
<p:inputTextarea id="ctrlPropertyDescLoc0" disabled="#{FormXYZ_01.propertyNone0}" cols="27" rows="3" />
</h:form>
The take-aways are, event had to be "change" and update had to point id attribute of the target control.
Also, don't forget to wrap your controls in form tags!
<h:form>...</h:form>

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

3 cascading dropdown menus with Ajax

I want to modify the example "ajaxify select" in PrimeFaces showcase application and introduce a third p:selectOneMenu with chooses depending on selection of second p:selectOneMenu.
Here is the modified code :
<h:form>
<p:growl id="msgs" showDetail="true"/>
<p:panel header="Double Combo" style="margin-bottom:10px;">
<h:panelGrid columns="3" cellpadding="5">
<p:selectOneMenu id="city" value="#{pprBean.city}">
<f:selectItem itemLabel="Select City" itemValue="" />
<f:selectItems value="#{pprBean.cities}" />
<p:ajax update="suburbs"
listener="#{pprBean.handleCityChange}" />
</p:selectOneMenu>
<p:selectOneMenu id="suburbs" value="#{pprBean.suburb}">
<f:selectItem itemLabel="Select Suburb" itemValue="" />
<f:selectItems value="#{pprBean.suburbs}" />
<p:ajax update="subsuburbs"
listener="#{pprBean.handleSuburbChange}" />
</p:selectOneMenu>
<p:selectOneMenu id="subsuburbs" value="#{pprBean.subsuburb}">
<f:selectItem itemLabel="Select Subsuburb" itemValue="" />
<f:selectItems value="#{pprBean.subsuburbs}" />
</p:selectOneMenu>
</h:panelGrid>
<p:separator />
<p:commandButton value="Submit" update="msgs"
actionListener="#{pprBean.displayLocation}"/>
</p:panel>
</h:form>
But the listener function #{pprBean.handleSuburbChange} is never executed. I saw in another forum that the dynamic code in ajax response don't include tag other that tag indicated in update attribute, but how can I do then?
In PPRBean code I added:
#Named("pprBean")
#RequestScoped
public class PPRBean implements Serializable {
// ...
public void handleSuburbChange() {
if (suburb != null && !suburb.equals("")) {
subsuburbs = subsuburbsData.get(suburb);
} else {
subsuburbs = new HashMap<String, String>();
}
log.info("subsuburbs:" + subsuburbs);
}
// ...
The listener won't be invoked if the selected item cannot be processed. You've put the bean in the request scope which means that it's garbaged when the response associated with the request is finished (i.e. when the browser is finished loading the page). So, when you submit the form, a new request will be fired and a brand new bean is created which in your case apparently doesn't prepare/prefill the list of suburbs in the (post)constructor in order to find the selected item (and execute the listener).
To fix this, you'd normally need to put the bean in the view scope by the JSF #ViewScoped annotation along with #ManagedBean.
#ManagedBean
#ViewScoped
public class Bean {
// ...
}
This way the bean instance will live as long as you're interacting with the same view. But as you're using CDI to manage the beans instead of JSF, you'd need to use #ConversationScoped instead and control the Conversation yourself.
#Named
#ConversationScoped
public class Bean {
#Inject
private Conversation conversation;
#PostConstruct
public void init() {
conversation.begin();
// ...
}
public void submit() {
// ...
conversation.end();
}
}

Resources