Primefaces 3.0.M2 SelectOneMenu Ajax行为的问题

时间:2011-06-22 05:49:20

标签: ajax jsf-2 facelets primefaces

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

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

上面的示例在同一个项目中正常工作。我使用的是NetBeans 7.0和GlassFish 3.1以及PrimeFaces 3.0.M2,这是最新一次(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变量为null。即使强制更改绑定的CityMap变量的值也不会更新selectCity下拉列表。

正如您所猜测的那样,我是JSF的新手,但问题因为我正在使用标签库的开发版本而更加复杂......

6 个答案:

答案 0 :(得分:2)

我为您在项目中描述的完全相同的情况创建了一个演示。我的页面上有州和城市<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

答案 1 :(得分:1)

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

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

注意狮心的话。页面中3.m4中更改的Primefaces名称空间使用此选项。 的xmlns:P = “http://primefaces.org/ui”

答案 2 :(得分:0)

我做了一个州 - &gt;城市在我的jsf项目中选择与你一样。我找到的唯一区别是:

  • 我的p:ajaxchange个活动:<p:ajax event="change" update="city" listener="#{contatoMB.filterCities}" />
  • 我的p:ajax位于f:selectItems之后,但这应该不是问题。
  • 城市选择中的f:selectItems列表是List<javax.faces.model.SelectItem>,而不是Map<String, City>,您是否尝试使用SelectItem代替地图?
  • 我的表单有一个id和prependId false <h:form id="contact-form" prependId="false">,再次,这应该不是问题。
  • 我的h:selectOneMenu位于p:panel内,部分PrimeFaces组件在其他组件内部或外部时以奇怪的方式运行。

如果这些都不起作用,那么问题就是你正在使用的PrimeFaces版本。我的PrimeFaces版本是2.2.1。

答案 3 :(得分:0)

我使用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">

似乎工作正常。

答案 4 :(得分:0)

也许它是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
}

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

答案 5 :(得分:0)

你应该添加

event="change"

到p:ajax