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 的新手,但由于我使用的是仍在开发中的标记库版本,问题变得更加复杂......
【问题讨论】:
这可能只是您的问题的一部分,但您的更新属性通过 idupdate="selectCity"
直接引用您的城市下拉组件。这样做的问题是,在 JSF 中 <h:form>
默认情况下会将其 id 添加到子元素中。尝试为您的<h:form>
指定以下属性,看看是否能解决您的问题,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】:
我为您在项目中描述的完全相同的情况创建了一个演示。我的页面上有一个州和城市<p:selectOneMenu/>
元素。您选择一个州,城市就会更新。如果选择了不同的州,则该城市将被删除,因为它可能不存在于该州中。
不同之处在于我使用<p:ajax event="change" update="cities, cs"/>
来更新元素,如果状态不同,我使用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
事件:<p:ajax event="change" update="city" listener="#contatoMB.filterCities" />
。
我的p:ajax
排在f:selectItems
之后,但这应该不是问题。
我在城市选择中的f:selectItems
列表是List<javax.faces.model.SelectItem>
而不是Map<String, City>
,您是否尝试过使用SelectItem
s 而不是您的地图?
我的表单有一个 id 和 prependId false <h:form id="contact-form" prependId="false">
,这应该不是问题。
我的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 绑定;