1

我有两个级联p:selectOneMenu组件。第一个显示来自 hashmap 的区域,第二个显示通过 ajax 选择区域的城市。但是当提交选择城市的表格时,我得到

验证错误:值无效

这是视图

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

这是豆子:

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

这是如何引起的,我该如何解决?

4

3 回答 3

1

当下拉列表的提交值未包含在可用值列表中时,您将收到此错误。所以这意味着与显示表单的 HTTP 请求相比,在表单提交的 HTTP 请求期间可用值列表发生了不兼容的变化。这反过来通常意味着支持 bean 是请求范围的,并且可用值列表未在其(后)构造函数中预初始化。

将 bean 放在视图范围内,或者添加根据请求参数正确预初始化可用值列表的代码,应该可以解决您的问题。

于 2012-10-16T10:44:50.120 回答
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.

于 2012-10-16T14:25:17.577 回答
0

您需要做的第一件事是告诉将 ajax 链接到一个事件。所以你可能希望它发生在 valueChange 事件上,所以你的 ajax 应该是:

<p:ajax update="tmil2" event="valueChange" listener="#{BeanAreaAndCity.handleCityChange()}"></p:ajax> 
于 2012-10-15T14:57:36.007 回答