Ответ 1
Поместите bean в область просмотра и избавьтесь от любой бизнес-логики в методах getter.
bean должен быть помещен в область представления, чтобы все предыдущие выборы и новые доступные элементы были запомнены, в противном случае произойдет сбой, если, например, Атрибут rendered
зависит от условия, которое было задано только в предыдущем запросе, или если JSF должен проверить выбранный элемент по списку доступных элементов.
Методы getter не должны содержать никакой бизнес-логики, так как они также будут вызываться во время a.o. фаза проверки. Вы должны использовать <f:ajax listener>
для выполнения бизнес-логики на основе изменения. Вы должны в методе слушателя также явно очистить выбранные значения дочерних выпадающих списков. Вы можете использовать <f:ajax render>
для обновления содержимого дочерних выпадающих списков.
Таким образом, так:
<h:selectOneMenu id="state" value="#{nodes.selectedState}">
<f:selectItem itemValue="#{null}" itemLabel="-- select --" />
<f:selectItems value="#{nodes.availableStates}" />
<f:ajax listener="#{nodes.changeState}" render="city region station" />
</h:selectOneMenu>
<h:selectOneMenu id="city" value="#{nodes.selectedCity}">
<f:selectItem itemValue="#{null}" itemLabel="-- select --" />
<f:selectItems value="#{nodes.availableCities}" />
<f:ajax listener="#{nodes.changeCity}" render="region station" />
</h:selectOneMenu>
<h:selectOneMenu id="region" value="#{nodes.selectedRegion}">
<f:selectItem itemValue="#{null}" itemLabel="-- select --" />
<f:selectItems value="#{nodes.availableRegions}" />
<f:ajax listener="#{nodes.changeRegion}" render="station" />
</h:selectOneMenu>
<h:selectOneMenu id="station" value="#{nodes.selectedStation}">
<f:selectItem itemValue="#{null}" itemLabel="-- select --" />
<f:selectItems value="#{nodes.availableStations}" />
</h:selectOneMenu>
с
@ManagedBean
@ViewScoped
public class Nodes {
private String selectedState; // getter+setter
private String selectedCity; // getter+setter
private String selectedRegion; // getter+setter
private String selectedStation; // getter+setter
private List<SelectItem> availableStates; // getter (no setter necessary!)
private List<SelectItem> availableCities; // getter (no setter necessary!)
private List<SelectItem> availableRegions; // getter (no setter necessary!)
private List<SelectItem> availableStations; // getter (no setter necessary!)
@EJB
private SomeService someService;
@PostConstruct
public void init() {
availableStates = someService.listStates();
}
public void changeState(AjaxBehaviorEvent event) {
availableCities = someService.listCities(selectedState);
selectedCity = selectedRegion = selectedStation = null;
availableRegions = availableStations = null;
}
public void changeCity(AjaxBehaviorEvent event) {
availableRegions = someService.listRegions(selectedCity);
selectedRegion = selectedStation = null;
availableStations = null;
}
public void changeRegion(AjaxBehaviorEvent event) {
availableStations = someService.listStations(selectedRegion);
selectedStation = null;
}
// Generate necessary getters+setters here. You should not change them.
}