1

I have two cascading p:selectOneMenu components. The first shows areas from a hashmap and the second shows cities for the selected area by ajax. But when submitting the form with the city selected, I get

Validation Error: Value is not valid

Here's the view

<p:selectOneMenu id="area" value="#{bean.area}">
    <f:selectItem itemLabel="Select Area" itemValue="" />
    <f:selectItems value="#{bean.areas}" />
    <p:ajax update="city" listener="#{bean.handleAreaChange()}" />
</p:selectOneMenu>
<p:selectOneMenu id="city" value="#{bean.city}">
    <f:selectItem itemLabel="Select City" itemValue="" />
    <f:selectItems value="#{bean.cities}" />
</p:selectOneMenu>  

Here's the bean:

private String area;
private String city;
private Map<String, String> areas = new HashMap<String, String>();
private Map<String, String> cities = new HashMap<String, String>();
private Map<String, Map<String, String>> allCities = new HashMap<String, Map<String,String>>();

public void handleAreaChange() {
    if (area != null && !area.isEmpty()) {
        cities = allCities.get(area);
    } else {
        cities = new HashMap<String, String>();
    }
}

How is this caused and how can I solve it?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555

3 Answers3

1

You will get this error when the submitted value of the dropdown is not contained in the list of available values. So this means that the list of available values has incompatibly changed during the HTTP request of the form submit as compared to the HTTP request of displaying the form. This in turn often means that the backing bean is request scoped and that the list of available values is not preinitialized in its (post)constructor.

Either putting the bean in the view scope, or adding code which properly preinitializes the list of available values based on request parameters, should fix your problem.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
1

As BalusC said the value (identifier) of the selectItem has changed. This can happen if your bean is request scoped or if the objects have changed server side.

A common solution I use is to set the value of the selectItem to an id of the object it represents.

Lets assume City and Area have unique identifiers (id) and looks like this:

public class City //or Area
{
    private Long id;
    private String name;

    //Rest of class
}

You can then introduce a converter for City and Area:

@FacesConverter("cityConverter")
public class CityConverter implements javax.faces.convert.Converter
{
    @Override
    public Object getAsObject(FacesContext ctx, UIComponent cmp, String str)
    {
        //Convert id to Object (City) and return it
    }

    @Override String getAsString(FacesContext ctx, UIComponent, Object obj)
    {
        //Return the id that represents the Object (City) here
        return ((City)obj).getId().toString();
    }
}

In your JSF page make use of the converter:

<p:selectOneMenu id="area" value="#{bean.area}" converter="areaConverter">
    <f:selectItem itemLabel="Select Area" itemValue="" />
    <f:selectItems value="#{bean.areas}" />
    <p:ajax update="city" listener="#{bean.handleAreaChange()}" />
</p:selectOneMenu>
<p:selectOneMenu id="city" value="#{bean.city}" converter="cityConverter">
    <f:selectItem itemLabel="Select City" itemValue="" />
    <f:selectItems value="#{bean.cities}" />
</p:selectOneMenu>

More about how to implement a FacesConverter on this site.

siebz0r
  • 18,867
  • 14
  • 64
  • 107
0

The first thing you need to do is to tell link the ajax to an event. So you probably want it to happen on the valueChange event so your ajax should be:

<p:ajax update="tmil2" event="valueChange" listener="#{BeanAreaAndCity.handleCityChange()}"></p:ajax> 
SteveS
  • 1,008
  • 3
  • 18
  • 32
  • It's the default event already. So this doesn't change anything for the OP. – BalusC Oct 16 '12 at 10:38
  • I always explicitly state the event. I didn't even realize that it would default to valueChange (though that makes sense I guess). Looks like I learned something today as well. That is the beauty of this forum. – SteveS Oct 16 '12 at 11:54