ValueChangeListener does not receive a call from <h: selectOneRadio>, which is placed on the side of a <h: panelGrid>
I ran into a problem with h: selectOneRadio valueChangeListener = "# {user.loadYesNo}" (I am using Mojarra 2-0-8 on Tomcat-7). If I remove the GridGrid containing 'h: selectOneRadio', then the limit of the value change is triggered.
View:
<!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"> <h:head><title> Starting JSF</title></h:head> <h:body> <h:form> <h:panelGrid column="2"> <h:outputLabel>User Name</h:outputLabel> <h:inputText id="loginName" value="#{user.userName}"></h:inputText> <h:outputLabel>Password</h:outputLabel> <h:inputSecret id="loginPassword" value="#{user.password}"></h:inputSecret> </h:panelGrid> <h:commandButton value="Submit" action ="#{user.validateLogin}"> <f:ajax execute="@form" render="yesNoRadioGrid message"></f:ajax> </h:commandButton> <h:panelGrid> <h:outputText id ="message" value="#{user.message}"></h:outputText> </h:panelGrid> <h:panelGrid id="yesNoRadioGrid"> <h:panelGrid columns="2" rendered="#{user.yesNoRadioGridFlag}"> <h:outputText id ="otherLbl" value="Select Yes or No"></h:outputText> <h:selectOneRadio id="yesNoRadio" value ="#{user.yesNoRadio}" valueChangeListener="#{user.loadYesNo}"> <f:selectItem itemValue="1" itemLabel="YES"></f:selectItem> <f:selectItem itemValue="0" itemLabel="NO"></f:selectItem> <f:ajax event="change" execute="@form" render="userDetailsGrid "></f:ajax> </h:selectOneRadio> </h:panelGrid> </h:panelGrid> <h:message for ="yesNoRadio"> </h:message> <h:panelGrid id="userDetailsGrid"> <h:panelGrid columns="2" rendered="#{user.userDetailsGridFlag}"> <h:outputLabel>Name :</h:outputLabel> <h:inputText id="customerName" value="#{user.customerName}"></h:inputText> <h:outputLabel>Salary: </h:outputLabel> <h:inputText id="customerSalary" value="#{user.customerSalary}"></h:inputText> </h:panelGrid> </h:panelGrid> </h:form> </h:body> </html> Model + controller mixed:
package com.jsf.test; import javax.faces.bean.*; import javax.faces.event.ValueChangeEvent; @ManagedBean public class User { private String userName; private String password; private String message; private String customerName; private String customerSalary; private Integer yesNoRadio; private Boolean yesNoRadioGridFlag; private Boolean userDetailsGridFlag; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public String getCustomerName() { return customerName; } public void setCustomerName(String customerName) { this.customerName = customerName; } public String getCustomerSalary() { return customerSalary; } public void setCustomerSalary(String customerSalary) { this.customerSalary = customerSalary; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Integer getYesNoRadio() { return yesNoRadio; } public void setYesNoRadio(Integer yesNoRadio) { this.yesNoRadio = yesNoRadio; } public Boolean getUserDetailsGridFlag() { return userDetailsGridFlag; } public void setUserDetailsGridFlag(Boolean userDetailsGridFlag) { this.userDetailsGridFlag = userDetailsGridFlag; } public Boolean getYesNoRadioGridFlag() { return yesNoRadioGridFlag; } public void setYesNoRadioGridFlag(Boolean yesNoRadioGridFlag) { this.yesNoRadioGridFlag = yesNoRadioGridFlag; } public String validateLogin() { if (userName.equals("xyz") && password.equals("xyz")) { message = "Login Success"; yesNoRadioGridFlag = true; } else { yesNoRadioGridFlag = false; message = "Login Failure"; } return message; } public void loadYesNo(ValueChangeEvent evt){ Integer yesNoValue = (Integer)evt.getNewValue(); setYesNoRadio(yesNoValue); userDetailsGridFlag = true; } } You need to place the bean in the viewport to preserve the basic condition of the rendered attribute for subsequent queries.
@ManagedBean @ViewScoped public class User { // ... } Not tied to a specific problem, valueChangeListener designed to be used whenever you want to have a hook on a server side value change event, which allows you to have both the old value and the new value in your hands. For example, to register an event. It is not intended to carry out business activities based on changes. To do this, you must use the listener <f:ajax> attribute.
So replace
<h:selectOneRadio id="yesNoRadio" value ="#{user.yesNoRadio}" valueChangeListener="#{user.loadYesNo}"> <f:selectItem itemValue="1" itemLabel="YES"></f:selectItem> <f:selectItem itemValue="0" itemLabel="NO"></f:selectItem> <f:ajax event="change" execute="@form" render="userDetailsGrid "></f:ajax> </h:selectOneRadio> from
<h:selectOneRadio id="yesNoRadio" value ="#{user.yesNoRadio}"> <f:selectItem itemValue="1" itemLabel="YES"></f:selectItem> <f:selectItem itemValue="0" itemLabel="NO"></f:selectItem> <f:ajax execute="@form" listener="#{user.loadYesNo}" render="userDetailsGrid"></f:ajax> </h:selectOneRadio> and remove the ValueChangeEvent attribute from the method.