Сделайте несколько зависимых/каскадных selectOneMenu выпадающих списков в JSF

Я пытаюсь сделать 4 зависимых меню.

Когда пользователь выбирает элемент из первого меню, во втором меню отображаются зависимые данные, а когда пользователь выбирает элемент из второго, третий отображает зависимые данные и т.д.

Пользователь будет видеть элементы только в первом меню, а остальные будут пустыми. Если он выбирает элемент в первом меню, второй отображает данные, а третий и четвертый остаются пустыми и т.д. Пользователь должен в конечном итоге выбрать записи из всех 4 меню.

<h:selectOneMenu id="first" value="#{nodes.selectState"}>
    <f:selectItems value="#{nodes.stateList}"/>
    <f:ajax render="second">
</h:selectOneMenu>
<h:selectOneMenu id="second" value="#{nodes.selectCity"}>
    <f:selectItems value="#{nodes.cityList}"/>
    <f:ajax render="third">
</h:selectOneMenu>
<h:selectOneMenu id="third" value="#{nodes.selectRegion"}>
    <f:selectItems value="#{nodes.regionList}"/>
    <f:ajax render="fourth">
</h:selectOneMenu>
<h:selectOneMenu id="fourth" value="#{nodes.selectStation"}>
    <f:selectItems value="#{nodes.stationList}"/>
</h:selectOneMenu>

узлы Java Class

private String selectState; //+setters, getters
private String selectCity; //+setters, getters
private String selectRegion; //+setters, getters
private String selectStation; //+setters, getters
private List<SelectItem> stateList; //+setters, getters
private List<SelectItem> cityList; //+setters, getters
private List<SelectItem> regionList; //+setters, getters
private List<SelectItem> stationList; //+setters, getters

public getStateList(){
    stateList= new ArrayList<SelectItem>();
    stateList.add(new SelectItem("A"));
}

public getCityList(){
    CityList= new ArrayList<SelectItem>();
    if(selectState.equals("A")){
        CityList.add(new SelectItem("B"));
    }
}

public getRegionList(){
    RegionList= new ArrayList<SelectItem>();
    if(selectCity.equals("B")){
        RegionList.add(new SelectItem("C"));
   }
}

public getStationList(){
    StationList= new ArrayList<SelectItem>();
    if(selectRegion.equals("C")){
        StationList.add(new SelectItem("D"));
    }
}

он работает только в первых двух меню, другие 2 меню получают нулевые значения

Ответы

Ответ 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.
}

См. также:

Ответ 2

В вашем коде есть опечатка. Для третьего меню вы указали имя "первым" вместо "третьего". Может быть из-за этой проблемы.

Ответ 3

Попробуйте это, это может помочь вам

Используя -Select City--, --Выберите Region--, --Select Station--, чтобы избежать исключения null-указателя.

    public getStateList(){
    stateList= new ArrayList<SelectItem>();
    stateList.add(new SelectItem("A"));
    }

    public getCityList(){
    CityList= new ArrayList<SelectItem>();
    if(selectState.equals("A"))
    {
      CityList.add(new SelectItem("B"));
    }
    else
    {
      CityList.add(new SelectItem("--Select City--"));
      selectCity = "--Select City--";
    }

    public getRegionList(){
    RegionList= new ArrayList<SelectItem>();
    if(selectCity.equals("B"))
    {
      RegionList.add(new SelectItem("C"));
    }
    else
    {
      RegionList.add(new SelectItem("--Select Region--"));
      selectRegion = "--Select Region--";
    }
    }

    public getStationList(){
    StationList= new ArrayList<SelectItem>();
    if(selectRegion.equals("C"))
    {
       StationList.add(new SelectItem("D"));
    }
    else
    {
      StationList.add(new SelectItem("Select Station"));
      selectStation = "--Select Station--";
    }
    }

Ответ 4

Вы столкнулись с этой проблемой, потому что у вас есть дважды id="first". Исправьте это, и он должен работать.