Hello,

I'm using MyFaces 1.1. I'm trying to update controls on a page when the user
changes the selection in a dropdown list. I can't quite seem to get it to
work as expected. Changes in the dropdown list do not seem to be firing the
value change event. When my dropdown list is populated with simple strings,
things seem to work just fine. I tried to simplify the problem by reducing
it down to just a single control on the page. For example, I have the
following JSP:

        <h:selectOneMenu id="colorsDDL" value="#{TestBean.colorValue}"
immediate="true" valueChangeListener="#{TestBean.processColorChange}"
onchange="this.form.submit();">
                <f:selectItems id="colorItems" value="#{TestBean.colorItems}" />
        </h:selectOneMenu>

My TestBean is a session scoped bean and the code is straightforward:

import java.util.Date;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;
import javax.faces.validator.ValidatorException;

public class TestBean {

        public TestBean() { }

        private String colorValue = "Red";
        
        public String getColorValue() {
                return colorValue;
        }
        
        public void setColorValue(String value) {
                this.colorValue = value;
        }
        
        private SelectItem[] colorItems = null;
        
        public SelectItem[] getColorItems() {
                if (colorItems == null) {
                        colorItems = new SelectItem[3];
                        colorItems[0] = new SelectItem("Red");
                        colorItems[1] = new SelectItem("Green");
                        colorItems[2] = new SelectItem("Blue");
                }
                return colorItems;
        }
        
        public void setColorItems(SelectItem[] items) {
                this.colorItems = items;
        }
        
        public void processColorChange(ValueChangeEvent evt) {
                System.out.println("Event source: " + ((UIInput)
evt.getSource()).getId());
                System.out.println("Old value: " + evt.getOldValue());
                System.out.println("New Value: " + evt.getNewValue());
        }
}

In this case, everything seems to work fine. The processColorChange method
is invoked when the dropdown list is changed, and the TestBean.setColorValue
method is invoked to update the model with the new value.

Now comes the problem. I change my JSP as follows:

        <h:selectOneMenu id="employeeDDL" value="#{TestBean.employeeValue}"
immediate="true" valueChangeListener="#{TestBean.processEmployeeChange}"
onchange="this.form.submit();" converter="EmployeeConverter"
validator="#{TestBean.validateEmployee}">
                <f:selectItems id="employeeItems" 
value="#{TestBean.employeeItems}" />
</h:selectOneMenu>

Note, that I am now using a converter and a validator. This is because my
dropdown list is being populated with object instances of the Employee
class, which looks like the following:

public class Employee implements Serializable {
  
  String name=null;
  Integer id=null;
  Date dateOfHire=null;
  
  /** Creates a new instance of Employee */
  public Employee() {
  }
  
  public Employee(String _name, Integer _id, Date _dateOfHire) {
    this.name=_name;
    this.id=_id;
    this.dateOfHire=_dateOfHire;
  }
  
  public String getName() {
    return name;
  }
  
  public void setName(String _name) {
    this.name=_name;
  }
  
  public Integer getId() {
    return id;
  }
  
  public void setId(Integer _id) {
    this.id=_id;
  }
  
  public Date getDateOfHire() {
    return dateOfHire;
  }
  
  public void setDateOfHire(Date _dateOfHire) {
    this.dateOfHire=_dateOfHire;
  }
  
  public String toString() {
    return new String(name + ";" + id + ";" + dateOfHire);
  }
}


I have written a Converter that looks like the following:

import java.util.Date;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;

public class EmployeeConverter implements Converter {
  
  /** Creates a new instance of EmployeeConverter */
  public EmployeeConverter() {
  }
  
  public String getAsString(FacesContext context, UIComponent component,
Object value) {
    String empString = null;
    if (value != null) {
        empString = value.toString();
    }
    return empString;
  }
  
  public Object getAsObject(FacesContext context, UIComponent component,
String value) {
    Employee empObject = null;
    String[] fields = value.split(";");
    empObject = new Employee();
    empObject.setName(fields[0]);
    empObject.setId(new Integer(fields[1]));
    empObject.setDateOfHire(new Date(fields[2]));
    return empObject;
  }
}



I have also written a validation method that basically does nothing other
than return, as long as the value passed to the validate method is an
instance of Employee.

I've modified my TestBean code as follows:



import java.util.Date;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;
import javax.faces.validator.ValidatorException;

public class TestBean {

        public TestBean() {     }
        
        private Employee[] employees = new Employee[] {
                        new Employee("Andrew Anderson", new Integer("12345"), 
new Date()),
                        new Employee("Bob Barker", new Integer("23456"), new 
Date()),
                        new Employee("Clive Conners", new Integer("34567"), new 
Date())
        };
                
        private String employeeValue = employees[0].toString();
        
        public String getEmployeeValue() {
                return employeeValue;
        }
        
        public void setEmployeeValue(String value) {
                employeeValue = value;
        }
        
        private SelectItem[] employeeItems = new SelectItem[] {
                new SelectItem(employees[0], employees[0].getName()),
                new SelectItem(employees[1], employees[1].getName()),
                new SelectItem(employees[2], employees[2].getName())
        };

        public SelectItem[] getEmployeeItems() {
                return employeeItems;
        }

        public void setEmployeeItems(SelectItem[] items) {
                this.employeeItems = items;
        }

        public void processEmployeeChange(ValueChangeEvent evt) {
                System.out.println("Event source: " + ((UIInput)
evt.getSource()).getId());
                System.out.println("Old value: " + evt.getOldValue());
                System.out.println("New Value: " + evt.getNewValue());          
        }
        
        
        public void validateEmployee(FacesContext context, UIComponent 
component,
Object value)
        throws ValidatorException {
                System.out.println("validate called ");
                if (value instanceof Employee) 
                        return;
                else 
                        throw new ValidatorException(
                                        new FacesMessage("Validation failed. 
Value is not an instance of
Employee."));
        }
}


I can see that the getAsString method in my EmployeeConverter is being
called when my page is rendered, I can also see that the getAsObject method
of my EmployeeConverter, and my validateEmployee method are being invoked
when a new value is selected within the dropdown. The object passed in to
the validateEmployee method is in fact an instance of the Employee class and
has the correct values (i.e., they match the selection from the dropdown),
however, the processEmployeeChange method is NOT being invoked, nor is the
setEmployeeValue method of my TestBean, so my model is not getting updated
with the new value either. I'm not sure if I'm doing something fundamentally
wrong here, or if I've stumbled across a bug or "feature". Please help. TIA.

TF
-- 
View this message in context: 
http://www.nabble.com/JSF-Newbie-needs-help-with-selectOneMenu-and-valueChangeListener-tf4341404.html#a12366849
Sent from the MyFaces - Users mailing list archive at Nabble.com.

Reply via email to