2つのSelectOneMenuコントロールの実装に問題があります。2番目のコントロールのデータは、最初のコントロールで行われた選択に依存します。 primeFacesショーケースのこの例は、実装したいものとほぼ同じです。 http://www.primefaces.org/showcase-labs/ui/pprSelect.jsf
ただし、データベースからデータを取得する必要があります。
上記の例は、同じプロジェクトで正しく機能しています。 NetBeans7.0とGlassFish3.1およびPrimeFaces3.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を初めて使用しますが、タグライブラリのまだ開発中のバージョンを使用しているという事実によって問題が悪化しています...
プロジェクトで説明したのとまったく同じ状況のデモを作成しました。ページに州と市の<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
Primefacesは別のことを試みています。理由はわかりません。まず第一に、これらのリリースは安定していないことを知っておく必要があります。あなたがfirebugでコードを分析するとき、あなたはこれを突き刺すでしょう。最初のコンボ都市を変更したときにIDが国と都市である2つのコンボは正しく更新されますが、都市コンボのIDがcitys_inputに変更されると、_inputプレフィックスが追加されます。 Primefacesのソースコードを分析するとき。 _inputまたは_panelを追加してIDを変更すると、トラバースツリーのようなコードがあります。したがって、2回目にコンボを変更した場合。都市の更新と言った以外はすべて完璧に機能しますが、新しいIDのcitys_inputがあるため、IDの都市を持つコンポーネントはありません。そのため、ajaxは正しく機能しません。しかし、彼らは3.0m4以降のリリースでこのバグを修正します。
これが問題です。この問題のもう1つの例は、誰かがこのためにjiraを開いているバグです。スプリングセキュリティj_usernameでログインを使用している場合、j_passwordをj_username_inputj_password_inputに変更します。したがって、これは標準を破り、コードは2番目のajaxリクエストでは機能しません。お役に立てれば..
ライオンハートの言葉に注意してください。ページの3.m4で変更されたPrimefaces名前空間はこれを使用します。 xmlns:p = "http://primefaces.org/ui"
名前空間でPrimeFaces3.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">
うまくいくようです。
追加するだけです
event="change"
p:ajaxへ
私はあなたがしたのと同じ方法で私の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を使用してみましたか?<h:form id="contact-form" prependId="false">
がありますが、これも問題にはなりません。h:selectOneMenu
はp:panel
の内部にあり、一部のPrimeFacesコンポーネントは、他のコンポーネントの内部または外部で奇妙な動作をします。これがうまくいかない場合は、使用しているPrimeFacesのバージョンに問題がある可能性があります。 PrimeFacesのバージョンは2.2.1です。
おそらくその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
}
それがあなたを助けるかどうかはわかりませんが、それは私がそれをする方法です。