OneMenu 不保留更改的值
OneMenu not persisting changed value
在 post (Hibernate Primefaces AutoComplete text) 之后,我稍微改变了实现方式。但是现在我遇到了一个问题。
即使我使用 AJAX 事件,我也不会保存所选值以填充第二个下拉列表。
我的CREATE.XHTML
<h:head></h:head>
<ui:debug rendered="true"/>
<body>
<h:form id="createAddressForm" prependId="true">
<!-- <p:messages autoUpdate="true" /> -->
<p:growl id="msgs" showDetail="true" />
<h:panelGrid columns="2" style="margin-bottom:10px" cellpadding="5">
<p:outputLabel for="countryDropDown" value="Country" />
<p:selectOneMenu id="countryDropDown" value="#{addressController.selectedIsoCountry}" >
<p:ajax listener="#{addressController.onCountryChange}" update="stateDropDown" />
<f:selectItem itemValue="" itemLabel="Select a country"/>
<f:selectItems value="#{addressController.countryMap}" />
</p:selectOneMenu>
<p:outputLabel for="stateDropDown" value="State" />
<p:selectOneMenu id="stateDropDown" value="#{addressController.state}" >
<f:selectItem itemValue="" itemLabel="Selecione a State" />
<f:selectItems value="#{addressController.stateMap}" />
</p:selectOneMenu>
</h:panelGrid>
</h:form>
</body>
</html>
这是AddressController.java
import java.util.Map;
import java.util.TreeMap;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.SessionScoped;
import javax.inject.Named;
import br.com.azulseguros.ejb.CountryEJB;
import br.com.azulseguros.entity.Country;
import br.com.azulseguros.entity.State;
@SessionScoped
@Named
public class AddressController {
@EJB
private CountryEJB countryEJB;
private String selectedIsoCountry = null;
private State state = null;
private Map<String, String> countryMap = null;
private Map<String, String> stateMap = null;
@PostConstruct
private void init() {
Map<String, String> retorno = new TreeMap<String, String>();
for (Country _tmp : countryEJB.findAll()) {
retorno.put(_tmp.getName(), _tmp.getIso());
}
countryMap = retorno;
}
public Map<String, String> getCountryMap() {
return countryMap;
}
public Map<String, String> getStateMap() {
return stateMap;
}
public String getSelectedIsoCountry() {
return selectedIsoCountry;
}
public State getState() {
return state;
}
public void setSelectedIsoCountry(String selectedIsoCountry) {
this.selectedIsoCountry = selectedIsoCountry;
}
public void setState(State state) {
this.state = state;
}
public void setCountryMap(Map<String, String> countryMap) {
this.countryMap = countryMap;
}
public void setStateMap(Map<String, String> stateMap) {
this.stateMap = stateMap;
}
public void onCountryChange() {
setStateMap(getStatesFromSelectedCountry());
}
private Map<String, String> getStatesFromSelectedCountry() {
Map<String, String> retorno = new TreeMap<String, String>();
if (selectedIsoCountry != null && !selectedIsoCountry.equals("")) {
for (State _tmp : countryEJB.findByIso(selectedIsoCountry).getStates()) {
retorno.put(_tmp.getName(), _tmp.getFu());
}
}
return retorno;
}
}
负责查找所有国家和州的 EJB 工作正常。这有很多问题,我不知道该怎么做才能解决它。
1 - 在我第一次调用该页面后,它调用了 init 方法 10 次;
2 - 之后它调用了 getStatesFromSelectedCountry 方法,甚至没有从第一个下拉列表中选择任何国家,然后再次调用了 init 方法;
3 - 当我选择一个国家时,它会调用 init 方法 7 次,然后调用 getStatesFromSelectedCountry(),但 selectedIsoCountry 为空。
bean 的 init
方法被多次调用,因为您已将 bean 定义为使用 javax.inject.Named
的 CDI bean,没有作用域,以及使用 javax.faces.bean.SessionScoped
定义为 JSF Managed Bean ;如果您打算使用 CDI bean,只需将后面的注释替换为 javax.enterprise.context.SessionScoped
。参见 Why are there different bean management annotations
从 CDI 的角度来看,bean 默认是 RequestScoped
,这也应该解释您遇到的第二个问题。
关于第三期,看这个Q/A:
- Why is the getter called so many times by the rendered attribute?
- Why JSF calls getters multiple times
在 post (Hibernate Primefaces AutoComplete text) 之后,我稍微改变了实现方式。但是现在我遇到了一个问题。
即使我使用 AJAX 事件,我也不会保存所选值以填充第二个下拉列表。
我的CREATE.XHTML
<h:head></h:head>
<ui:debug rendered="true"/>
<body>
<h:form id="createAddressForm" prependId="true">
<!-- <p:messages autoUpdate="true" /> -->
<p:growl id="msgs" showDetail="true" />
<h:panelGrid columns="2" style="margin-bottom:10px" cellpadding="5">
<p:outputLabel for="countryDropDown" value="Country" />
<p:selectOneMenu id="countryDropDown" value="#{addressController.selectedIsoCountry}" >
<p:ajax listener="#{addressController.onCountryChange}" update="stateDropDown" />
<f:selectItem itemValue="" itemLabel="Select a country"/>
<f:selectItems value="#{addressController.countryMap}" />
</p:selectOneMenu>
<p:outputLabel for="stateDropDown" value="State" />
<p:selectOneMenu id="stateDropDown" value="#{addressController.state}" >
<f:selectItem itemValue="" itemLabel="Selecione a State" />
<f:selectItems value="#{addressController.stateMap}" />
</p:selectOneMenu>
</h:panelGrid>
</h:form>
</body>
</html>
这是AddressController.java
import java.util.Map;
import java.util.TreeMap;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.SessionScoped;
import javax.inject.Named;
import br.com.azulseguros.ejb.CountryEJB;
import br.com.azulseguros.entity.Country;
import br.com.azulseguros.entity.State;
@SessionScoped
@Named
public class AddressController {
@EJB
private CountryEJB countryEJB;
private String selectedIsoCountry = null;
private State state = null;
private Map<String, String> countryMap = null;
private Map<String, String> stateMap = null;
@PostConstruct
private void init() {
Map<String, String> retorno = new TreeMap<String, String>();
for (Country _tmp : countryEJB.findAll()) {
retorno.put(_tmp.getName(), _tmp.getIso());
}
countryMap = retorno;
}
public Map<String, String> getCountryMap() {
return countryMap;
}
public Map<String, String> getStateMap() {
return stateMap;
}
public String getSelectedIsoCountry() {
return selectedIsoCountry;
}
public State getState() {
return state;
}
public void setSelectedIsoCountry(String selectedIsoCountry) {
this.selectedIsoCountry = selectedIsoCountry;
}
public void setState(State state) {
this.state = state;
}
public void setCountryMap(Map<String, String> countryMap) {
this.countryMap = countryMap;
}
public void setStateMap(Map<String, String> stateMap) {
this.stateMap = stateMap;
}
public void onCountryChange() {
setStateMap(getStatesFromSelectedCountry());
}
private Map<String, String> getStatesFromSelectedCountry() {
Map<String, String> retorno = new TreeMap<String, String>();
if (selectedIsoCountry != null && !selectedIsoCountry.equals("")) {
for (State _tmp : countryEJB.findByIso(selectedIsoCountry).getStates()) {
retorno.put(_tmp.getName(), _tmp.getFu());
}
}
return retorno;
}
}
负责查找所有国家和州的 EJB 工作正常。这有很多问题,我不知道该怎么做才能解决它。 1 - 在我第一次调用该页面后,它调用了 init 方法 10 次; 2 - 之后它调用了 getStatesFromSelectedCountry 方法,甚至没有从第一个下拉列表中选择任何国家,然后再次调用了 init 方法; 3 - 当我选择一个国家时,它会调用 init 方法 7 次,然后调用 getStatesFromSelectedCountry(),但 selectedIsoCountry 为空。
bean 的 init
方法被多次调用,因为您已将 bean 定义为使用 javax.inject.Named
的 CDI bean,没有作用域,以及使用 javax.faces.bean.SessionScoped
定义为 JSF Managed Bean ;如果您打算使用 CDI bean,只需将后面的注释替换为 javax.enterprise.context.SessionScoped
。参见 Why are there different bean management annotations
从 CDI 的角度来看,bean 默认是 RequestScoped
,这也应该解释您遇到的第二个问题。
关于第三期,看这个Q/A:
- Why is the getter called so many times by the rendered attribute?
- Why JSF calls getters multiple times