Primefaces 3.0.M2 SelectOneMenu Ajax 行为的问题

Posted

技术标签:

【中文标题】Primefaces 3.0.M2 SelectOneMenu Ajax 行为的问题【英文标题】:Trouble with Primefaces 3.0.M2 SelectOneMenu Ajax behavior 【发布时间】:2011-09-20 02:21:30 【问题描述】:

我在实现两个 SelectOneMenu 控件时遇到问题,其中第二个控件中的数据取决于第一个控件中的选择。 primeFaces 展示中的这个示例与我要实现的几乎相同:http://www.primefaces.org/showcase-labs/ui/pprSelect.jsf

除了我必须从数据库中获取数据。

上面的例子在同一个项目中工作正常。我正在使用带有 GlassFish 3.1 和 PrimeFaces 3.0.M2 的 NetBeans 7.0,这是最新的下降(2011 年 6 月 20 日)。

附上JSF页面和托管bean的源码。

<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"
  xmlns:p="http://primefaces.prime.com.tr/ui" 
  xmlns:f="http://java.sun.com/jsf/core">
<h:head><title>Facelet Title</title></h:head>
<h:body>
 <p:log />
    <center>
        <h:form>
            <h:outputText value="State: "/>
            <p:selectOneMenu id="selectState" value="#stateCityBean.selectedStateArray">
                <f:selectItem itemLabel="Select Any" itemValue="Empty String"/>
                <p:ajax update="selectCity" listener="#stateCityBean.updateCityMap"/>
                <f:selectItems value="#stateCityBean.stateMap" />
            </p:selectOneMenu>
            <p></p>
            <h:outputText value="City: "/>
            <p:selectOneMenu id="selectCity" value="#stateCityBean.selectedCityArray">
                <f:selectItem itemLabel="Select Any" itemValue="Empty String"/>
                <f:selectItems value="#stateCityBean.cityMap"/>
            </p:selectOneMenu>
        </h:form>
    </center>
</h:body>

StateCityBean.java

package com.xyz.mbeans;
import com.iwizability.priceinfo.dao.*;
import com.iwizability.priceinfo.pojo.*;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.context.Flash;
import javax.faces.event.ValueChangeEvent;

@ManagedBean
@SessionScoped
public class StateCityBean 
private String selectedStateArray;
private Map<String, State> StateMap;
private Map<String, City> CityMap;
private String selectedCityArray;

public StateCityBean() 
    System.out.println("Inside.............. ");
    StateMap = new LinkedHashMap<String, State>();
    CityMap = new LinkedHashMap<String, City>();


public String getSelectedStateArray() return selectedStateArray;

public void setSelectedStateArray(String selectedStateArray) this.selectedStateArray = selectedStateArray;

public Map<String, State> getStateMap() 
    StateDaoImpl stateObj = new StateDaoImpl();
    StateMap = stateObj.getState();
    return StateMap;


public void setStateMap(Map<String, State> stateArray) this.StateMap = stateArray;

public String getSelectedCityArray() return selectedCityArray;

public void setSelectedCityArray(String selectedCityArray) this.selectedCityArray = selectedCityArray;

public Map<String, City> getCityMap() 
    CityDaoImpl cityObj = new CityDaoImpl();
    int stateId = 0;
    if (selectedStateArray != null && !selectedStateArray.equals("")) 
        stateId = StateMap.get(selectedStateArray).getId();
    
    CityMap = cityObj.getCity(stateId);
    return CityMap;


public void setCityMap(Map<String, City> CityArray) 
    this.CityMap = CityArray;


public void updateCityMap() 
    CityDaoImpl cityObj = new CityDaoImpl();
    int stateId = 0;
    if (selectedStateArray != null && !selectedStateArray.equals("")) 
        stateId = StateMap.get(selectedStateArray).getId();
        this.CityMap = cityObj.getCity(stateId);
    
 

在调试时,我可以看到 updateCityMap 方法被调用,但 SelectedStateArray 变量为空。即使强制更改绑定 CityMap 变量的值也不会更新 selectCity 下拉菜单。

正如您所猜到的,我是 JSF 的新手,但由于我使用的是仍在开发中的标记库版本,问题变得更加复杂......

【问题讨论】:

这可能只是您的问题的一部分,但您的更新属性通过 id update="selectCity" 直接引用您的城市下拉组件。这样做的问题是,在 JSF 中 &lt;h:form&gt; 默认情况下会将其 id 添加到子元素中。尝试为您的&lt;h:form&gt; 指定以下属性,看看是否能解决您的问题,prependId="false" @maple_shaft:这是我见过的所有示例中使用 update 属性的方式...我尝试禁用 prependId 但它似乎无法解决问题。 所以,我向 p:ajax 添加了一个 event="valueChange" 属性,现在出现错误:j_idt8:selectState: Validation Error: Value is not valid 在查找验证错误时,似乎网络充满了这个问题。使用 JSF 以及特别使用 PrimeFaces:primefaces.prime.com.tr/forum/viewtopic.php?f=3&t=6947 java.net/blogs/lamine_ba coderanch.com/t/501774/JSF/java/… 我尝试将范围更改为 viewscoped,但是,这对我来说也不起作用...... 哇,这是一个奇怪的问题!我在其中一个线程中看到它尝试覆盖 equals 和 hashCode。你试过这个吗?对于某些人来说,这似乎解决了这个问题。如果这对您不起作用,我愿意就这个问题发布悬赏。 感谢枫!我现在完全迷失了......不明白这段代码(primefaces.org/showcase-labs/ui/pprSelect.jsf)如何在同一个项目中正常工作 【参考方案1】:

我为您在项目中描述的完全相同的情况创建了一个演示。我的页面上有一个州和城市&lt;p:selectOneMenu/&gt; 元素。您选择一个州,城市就会更新。如果选择了不同的州,则该城市将被删除,因为它可能不存在于该州中。

不同之处在于我使用&lt;p:ajax event="change" update="cities, cs"/&gt; 来更新元素,如果状态不同,我使用actionListener 来更新城市。

<p:selectOneMenu id="states" value="#dataBean.selectedState"
   valueChangeListener="#dataBean.stateChangeListener(event)"
   style="width: 150px;">
   <f:selectItem itemLabel="" itemValue=""/>
   <f:selectItems value="#dataBean.states"/>
   <p:ajax event="change" update="cities, cs"/>
</p:selectOneMenu>
<h:outputLabel value="City:" for="cities"/>
<p:selectOneMenu id="cities" 
   value="#dataBean.selectedCity" 
   style="width: 150px;">
   <f:selectItem itemLabel="" itemValue=""/>
   <f:selectItems value="#dataBean.cities"/>
   <p:ajax event="change" update="cs" />
 </p:selectOneMenu>

整个项目和演示代码可以在我的博客上找到。我看到了这篇文章并决定发布我的项目。 [博客]:http://javaevangelist.blogspot.com/2012/07/primefaces-ajax-enabled.html

【讨论】:

【参考方案2】:

Primefaces 正在尝试不同的东西。我不知道为什么。首先你必须知道这些版本是不稳定的。 当你用 firebug 分析代码时,你会推动它。 让我们假设两个拥有国家和城市的组合 当您更改第一个组合城市更新正确但城市组合的 id 更改为 city_input 他们添加 _input 前缀。当我分析 primefaces 源代码时。如果通过添加_input或_panel访问更改id,则有类似遍历树的代码。因此,如果您第二次更改组合。一切都很完美,除了你说更新城市,但没有组件有 id 城市,因为它有新的 id 城市输入。所以你的 ajax 不能正常工作。但是他们在 3.0m4 或之后的版本中更正了这个错误。

这就是问题所在。这个问题的另一个例子是有人为此打开 jira 的错误。 如果您使用 spring security j_username 登录,j_password 更改为 j_username_input j_password_input。所以这打破了标准,代码在第二个 ajax 请求中不起作用。 希望这会有所帮助..

注意lionhearts的话。在 3.m4 中更改的 Primefaces 名称空间在页面中使用此。 xmlns:p="http://primefaces.org/ui"

【讨论】:

【参考方案3】:

我在我的 jsf 项目中做了一个州 -> 城市选择,就像你做的一样。我发现的唯一区别是:

我的p:ajax 有一个change 事件:&lt;p:ajax event="change" update="city" listener="#contatoMB.filterCities" /&gt;。 我的p:ajax 排在f:selectItems 之后,但这应该不是问题。 我在城市选择中的f:selectItems 列表是List&lt;javax.faces.model.SelectItem&gt; 而不是Map&lt;String, City&gt;,您是否尝试过使用SelectItems 而不是您的地图? 我的表单有一个 id 和 prependId false &lt;h:form id="contact-form" prependId="false"&gt;,这应该不是问题。 我的h:selectOneMenu 位于p:panel 内部,某些 PrimeFaces 组件在其他组件内部或外部时会以奇怪的方式表现。

如果这些都不起作用,则问题可能出在您使用的 PrimeFaces 版本上。我的 PrimeFaces 版本是 2.2.1。

【讨论】:

【参考方案4】:

我使用带有命名空间的 PrimeFaces 3.0.M4:

<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"
  xmlns:p="http://primefaces.org/ui">

它似乎工作正常。

【讨论】:

【参考方案5】:

也许它是 primefaces 版本,但您的 bean 中的更新方法看起来相当复杂。

为什么不从 ajax 事件中检索选择的对象呢?这样就不需要定义那个变量了。

public void update(AjaxBehaviorEvent event)

    Object selectOneMenuObject = ((UIOutput)event.getSource()).getValue();

    //String selectedStateArray = (String)((UIOutput)event...
    //update temporary collection of second SelectOneMenu

不知道这是否对你有帮助,但我就是这样做的。

【讨论】:

【参考方案6】:

你应该添加

event="change"

到 p:ajax

【讨论】:

以上是关于Primefaces 3.0.M2 SelectOneMenu Ajax 行为的问题的主要内容,如果未能解决你的问题,请参考以下文章

Primefaces:如何在 primefaces 3.5 中为菜单栏设置粘性

将 primefaces 数据表与 org.primefaces.component.datatable.DataTable 绑定;

实现PrimeFaces扩展时出错

使用ajax从jsf中的primefaces树选定项设置primefaces selectOneMenu默认值

JSF 2 PrimeFaces 安装

在 PrimeFaces 中添加 Angular Js - JSF