在JSF中创建多个依赖/级联selectOneMenu下拉列表

时间:2013-05-04 19:24:52

标签: jsf hierarchy selectonemenu cascading ajax-update

我正在尝试制作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类

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个菜单中工作,其他2个菜单获得空值

4 个答案:

答案 0 :(得分:7)

将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.
}

另见:

答案 1 :(得分:1)

您的代码中存在拼写错误。对于第三个菜单,您将id名称设为“first”而不是“third”。可能是因为那个问题。

答案 2 :(得分:-1)

试试这个,它可能对你有帮助

使用--Select City--, - 选择Region--, - 选择Station--以避免空指针Exception。

    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--";
    }
    }

答案 3 :(得分:-3)

您遇到此问题,因为您有两次id="first"。 解决这个问题,它应该可行。