Проблема с Primefaces 3.0.M2 SelectOneMenu Ajax поведение
У меня возникают проблемы с внедрением двух элементов управления SelectOneMenu, где данные во втором зависят от выбора, сделанного в первом. Этот пример в витрине firstFaces почти такой же, как я хочу реализовать: http://www.primefaces.org/showcase-labs/ui/pprSelect.jsf
за исключением того, что мне нужно получить данные из базы данных.
Приведенный выше пример корректно работает в одном проекте. Я использую NetBeans 7.0 с GlassFish 3.1 и PrimeFaces 3.0.M2, последнее падение (20 июня 2011 г.).
Подключен исходный код страницы 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, не обновляет dropCity.
Как вы бы догадались, я новичок в 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
Направляющие пытаются что-то отличить. Я не знаю, почему. Прежде всего, вы должны знать, что эти выпуски нестабильны.
Когда вы проанализируете код с помощью firebug, вы засунете это.
Предположим, что два комбо, у которых есть идентификаторы стран и городов
когда вы изменили первое обновление данных комбо-городов, но вместо "city combo" id измените на cities_input, добавьте префикс _input. Когда я анализирую исходный код. Там код что-то вроде дерева траверс, если посетил изменение идентификатора, добавив _input или _panel. Поэтому, если вы измените комбо во второй раз. Все работает отлично, за исключением упомянутых городов обновления, но нет компонента, у которого есть города id, потому что у него есть новый идентификатор city_input. Таким образом, ваш аякс работает неправильно. Но они исправляют эту ошибку в 3.0m4 или после релизов.
Это проблема. Другим примером этой проблемы является ошибка для кого-то открыть jira для этого.
Если вы используете логин с spring безопасностью j_username, j_password измените на j_username_input j_password_input. Таким образом, это нарушает стандарт, и код не работает во втором запросе ajax.
Надеюсь, это поможет.
обратите внимание на слова львиц-сердец. Пространства имен интерфейсов, измененные в 3.m4 на страницах, используют это.
XMLNS: р = "http://primefaces.org/ui"
Ответ 3
Я сделал государство → город в моем проекте jsf так же, как и вы. Единственные различия, которые я нашел, следующие:
- my
p:ajax
имеет событие change
: <p:ajax event="change" update="city" listener="#{contatoMB.filterCities}" />
.
- my
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">
, опять же, это не должно быть проблемой.
- my
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
Может быть, это версия с перформами, но ваш метод обновления в вашем 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"
to p: ajax