【问题标题】:Trouble with Primefaces 3.0.M2 SelectOneMenu Ajax behaviorPrimefaces 3.0.M2 SelectOneMenu Ajax 行为的问题
【发布时间】: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)如何在同一个项目中正常工作

标签: ajax jsf-2 facelets primefaces


【解决方案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

            【讨论】:

              猜你喜欢
              • 2023-03-16
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-11-23
              • 2015-11-05
              • 1970-01-01
              • 2014-11-13
              • 1970-01-01
              相关资源
              最近更新 更多