[英]Populating a chlid jSF selectOneMenu - implicit value validation error
正如您在屏幕截圖中看到的,我對屬性“member.city”有一個JSF隱式值驗證錯誤 。 目的是通過ajax - 在上一個Country Select one菜單上選擇一個國家后填充城市選擇一個菜單。 這是通過使用selectOneMenu更改偵聽器和ajax來更新顯示城市列表的組件來實現的。 但是,我收到驗證錯誤,表單未提交。
我嘗試使用和不使用實體(hascode和equals方法) ,但是徒勞無功。 我使用分離的Managed Bean ViewScoped來檢索已過濾的列表,但是徒勞無功。 **
如果我用檢索所有城市的列表替換過濾的城市列表(在xhtml表單中,用
<f:selectItems value="#{cityBean.citiesByCountry}" />
替換<f:selectItems value="#{cityBean.citiesByCountry}" />
<f:selectItems value="#{cityBean.all}" />
,沒有驗證錯誤,表單已成功提交。
**這是代碼:
形成:
<p:outputLabel for="country" value="#{i18n.country}" />
<p:selectOneMenu valueChangeListener="#{cityBean.selectCountry}" rendered="true" id="country" value="#{newMember.country}" converter="#{countryBean.converter}"
style="width:160px;text-align:left;border:thin solid gray;"
required="true" requiredMessage="#{i18n.required}">
<f:selectItems value="#{countryBean.all}" var="countryname" itemLabel="#{countryname.name}"/>
<p:ajax event="change" update="city" />
</p:selectOneMenu>
<p:message for="country" />
<p:outputLabel for="city" value="#{i18n.city}" />
<p:selectOneMenu rendered="true" id="city" value="#{newMember.city}" converter="#{cityBean.converter}" converterMessage="Conversion error!"
style="width:160px;text-align:left;border:thin solid gray;"
required="true" requiredMessage="#{i18n.required}">
<f:selectItems value="#{cityBean.citiesByCountry}" var="cityname" itemLabel="#{cityname.cityname}"/>
</p:selectOneMenu>
<p:message for="city" />
市實體負責人:
@XmlRootElement
@Entity
@Table(name = "city", schema = "public")
@NamedQueries({
@NamedQuery(name = "City.findAll", query = "SELECT c FROM City c"),
@NamedQuery(name = "City.findById", query = "SELECT c FROM City c WHERE c.id = :id"),
@NamedQuery(name = "City.findByCountry", query = "SELECT c FROM City c WHERE c.country = :country"),
@NamedQuery(name = "City.findByCountryOrderedByName", query = "SELECT c FROM City c WHERE c.country = :country ORDER BY c.cityname ASC") })
@NamedNativeQueries({ @NamedNativeQuery(name = "City.findCountryNativeSQL", query = "select * from city c where c.countrybeta = :country.betacode", resultClass = City.class) })
public class City implements java.io.Serializable {
private static final long serialVersionUID = 3364735938266980295L;
private int id;
private Integer version;
private Country country;
private String cityname;
private String district;
private int population;
private Set<Member> members = new HashSet<Member>(0);
public City() {
}
// ...remainder of entity code (contructors and fields..)
豆子:
@Named
@Stateful
@ConversationScoped
public class CityBean implements Serializable {
private static final long serialVersionUID = 1L;
private City city;
private List<City> cityList;
public City getCity() {
return this.city;
}
private Country selectedCountry;
@Inject
private Conversation conversation;
@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager entityManager;
// remainder of code....
// The List that works fine with Select one Menu
public List<City> getAll() {
CriteriaQuery<City> criteria = this.entityManager.getCriteriaBuilder()
.createQuery(City.class);
return this.entityManager.createQuery(
criteria.select(criteria.from(City.class))).getResultList();
}
@PostConstruct
public void init() {
setCityList(getCitiesByCountry());
}
public List<City> getCityList() {
return cityList;
}
public void setCityList(List<City> cityList) {
this.cityList = cityList;
}
/**
* The List That triggers a jsf value validation error
* @return List of Cities by Country ordered by city name
*/
public List<City> getCitiesByCountry() {
TypedQuery<City> query = this.entityManager.createNamedQuery(
"City.findByCountryOrderedByName", City.class);
query.setParameter("country", selectedCountry);
return query.getResultList();
}
// The Select One Menu Listener
public void selectCountry(ValueChangeEvent event) {
if (event != null) {
selectedCountry = (Country) event.getNewValue();
}
}
// getters and setters....
ENV: - JSF 21 - Hibernate - JBoss AS 7.1 - PrimeFaces 3.5 - Linux 3.5 / Firefox 18.0.2
您的具體問題是由於您沒有在@PostConstruct
啟動對話而導致的,因此bean的行為類似於請求作用域。 這樣,在處理表單提交期間城市列表將不兼容地更改並變為空(因此在可用項列表中找不到所選項,因此此驗證錯誤)。
您需要在@PostConstruct
啟動對話。
conversation.begin();
與具體問題無關 ,使用valueChangeListener
並在getter方法中執行業務邏輯是錯誤的方法。 您根本不應該在getter方法中執行業務邏輯。 這顯然效率低下。 他們應該只返回已經准備好的bean屬性。
重寫您的邏輯如下:
<p:selectOneMenu value="#{bean.country}" ...>
<f:selectItems value="#{bean.countries}" />
<p:ajax listener="#{bean.updateCities}" update="city" />
</p:selectOneMenu>
<p:selectOneMenu id="city" value="#{bean.city}" ...>
<f:selectItems value="#{bean.cities}" />
</p:selectOneMenu>
同
private Country country;
private List<Country> countries;
private City city;
private List<City> cities;
@PostConstruct
public void init() {
countries = service.listCountries();
public void updateCities() {
cities = service.listCities(country);
}
// Add/generate normal!! getters/setters.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.