Problème avec Primefaces 3.0.M2 comportement SelectOneMenu Ajax
j'ai du mal à implémenter deux contrôles SelectOneMenu, où les données dans le second dépendent de la sélection faite dans le premier. Cet exemple sur la vitrine primeFaces est presque le même que celui que je veux implémenter:http://www.primefaces.org/showcase-labs/ui/pprSelect.jsf
sauf que je dois obtenir les données à partir d'une base de données.
L'exemple ci-dessus fonctionne correctement dans le même projet. J'utilise NetBeans 7.0 avec GlassFish 3.1 et PrimeFaces 3.0.M2, la dernière baisse (20 juin 2011).
le code source de la page JSF et de la fève gérée est joint.
<?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);
}
}
}
au débogage, je peux voir que la méthode updateCityMap est invoquée mais que la variable SelectedStateArray est nulle. Même la modification de force de la valeur de la variable liée CityMap ne met pas à jour la baisse de sélectcity.
Comme vous l'avez deviné, je suis nouveau à JSF, mais le problème est aggravé par le fait que j'utilise une version encore en développement de la bibliothèque tag...
6 réponses
j'ai créé une démo pour exactement la même situation que vous décrivez dans votre projet. J'ai un état et une ville <p:selectOneMenu/>
éléments sur ma page. Vous sélectionnez un état, et les villes mettent à jour. Si un état différent est sélectionné, la ville est effacée car elle ne peut pas exister dans l'état.
la différence est que j'utilise <p:ajax event="change" update="cities, cs"/>
pour mettre à jour les éléments, et un actionListener pour mettre à jour la ville si l'état est différent.
<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>
l'ensemble du projet et du code de démonstration se trouve sur mon blog. J'ai vu ce post et a décidé de poster mon projet. [blog]:http://javaevangelist.blogspot.com/2012/07/primefaces-ajax-enabled.html
Primefaces essaie quelque chose de diffent. Je ne sais pas pourquoi. Tout d'abord, vous devez savoir que ces rejets ne sont pas stables. Quand vous analysez le code avec firebugg vous poussez ceci. Supposons deux combo qui a ids pays et villes lorsque vous avez changé la première mise à jour de combo cities correctement, mais les villes combo' id changent en city_input ils ajoutent le préfixe _input. Quand j'analyse le code source de primefaces. Il y a des codes quelque chose comme l'arbre de traverse si visited change id en ajoutant _input ou _panel. Donc, si vous changez le combo pour la deuxième fois. Tout fonctionne parfaitement sauf que vous avez dit update cities mais il n'y a aucun composant qui a id cities parce qu'il a de nouvelles id cities_input. Si votre ajax ne fonctionne pas correctement. Mais ils corrigent ce bug en 3.0m4 ou après.
C'est le problème. Un autre exemple de ce problème est de mettre quelqu'un sur écoute pour ouvrir jira. Si vous utilisez la connexion avec ressort de sécurité j_username, j_password changement de j_username_input j_password_input. Donc, cela casse le standart et le code ne fonctionnent pas dans les deuxièmes requêtes ajax. Espérons que cette aide..
faites attention aux mots du cœur de lion. Les espaces de noms de Primefaces ont changé en 3.m4 dans les pages utilisez ceci. xmlns: p = "http://primefaces.org/ui"
j'ai fait un choix d'état - > de ville dans mon projet jsf de la même façon que vous. Les seules différences que j'ai trouvé sont:
- mon
p:ajax
a unchange
événement:<p:ajax event="change" update="city" listener="#{contatoMB.filterCities}" />
. - mon
p:ajax
vient en dernier après lef:selectItems
mais cela ne devrait pas être le problème. - mon
f:selectItems
liste dans la ville selectList<javax.faces.model.SelectItem>
et pasMap<String, City>
, avez-vous essayé d'utiliserSelectItem
s au lieu de votre carte? - mon formulaire dispose d'un identifiant et prependId false
<h:form id="contact-form" prependId="false">
, encore une fois, ce ne devrait pas être le problème. - mon
h:selectOneMenu
est dans unp:panel
, certains composants de PrimeFaces se comportent d'une manière étrange à l'intérieur ou à l'extérieur de certains autres composants.
si rien de tout cela ne fonctionne peut-être le problème est la version PrimeFaces que vous utilisez. Ma version PrimeFaces est 2.2.1.
j'utilise PrimeFaces 3.0.M4 avec des espaces de noms:
<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">
Il semble bien fonctionner.
peut-être que c'est la version primefaces mais votre méthode de mise à jour dans votre haricot semble assez compliquée.
Pourquoi ne pas récupérer l'Objet de la sélection de l'ajax événement? de cette façon vous n'avez pas besoin de définir cette variable.
public void update(AjaxBehaviorEvent event)
{
Object selectOneMenuObject = ((UIOutput)event.getSource()).getValue();
//String selectedStateArray = (String)((UIOutput)event...
//update temporary collection of second SelectOneMenu
}
Je ne sais pas si cela vous aidera, mais c'est exactement ce que je fais.