el_zako
el_zako

Reputation: 152

JSF ValueChangeEvent: how do I change the options on one SelectOneMenu based on my selection on a previous SelectOneMenu?

Ok I've been stuck with this for a couple of days (understatement).

Say I have a selectOneMenu

    <h:selectOneMenu id="selectFamily" 
         valueChangeListener="#{menuBean.changeFamily}"    
         onclick="submit()" 
         immediate="true" >
        <f:selectItems id="familyNames" value="#{menuBean.familyNames}" />
      </h:selectOneMenu>

And I want to change the options on another selectOneMenu based on the options selected in this previous selectOneMenu.

   <h:selectOneMenu id="selectFunction" immediate="true">
        <f:selectItems id="functions" value="#{menuBean.functions}" />
    </h:selectOneMenu>

How do I do this?Reading around, I have a couple of ideas of how to do it, but I just can't seem to get it right. I'm sorry I'll just dump the bean class here hoping someone can guide me.

public class MenuBean {

/** Creates a new instance of MenuBean */
public MenuBean() {
} 

private SelectItem[] familyNames = {
    new SelectItem((Integer) 1,"Operations"),
    new SelectItem((Integer) 2, "Special"),
    new SelectItem((Integer) 3, "Support")};

public SelectItem[] getFamilyNames() {
    return familyNames;
}

private SelectItem[] functions = {new SelectItem("Select Function")};

private SelectItem[] operationsFunctions = {
    new SelectItem("Air/Ocean Freight"),
    new SelectItem("Customs"),
    new SelectItem("Land Transport"),
    new SelectItem("Logistics/SCM"),
    new SelectItem("Rail Transport"),
    new SelectItem("Special")
};

private SelectItem[] specialFunctions = {
    new SelectItem("General Management"),
    new SelectItem("Quality & Processes")
};

private  SelectItem[] supportFunctions = {
    new SelectItem("Finance/Controlling"),
    new SelectItem("Human Resources"),
    new SelectItem("ICT"),
    new SelectItem("Legal Affairs"),
    new SelectItem("Marketing/Public Relations"),
    new SelectItem("Procurement"),
};

public SelectItem[] getFunctions(int n) {

    if (n==1) {
        functions = operationsFunctions;
    } else if (n==2) {
        functions = specialFunctions;
    } else if (n==3) {
        functions = supportFunctions;
    }

    return functions;
}

public void setFunctions(SelectItem[] function) {
    this.functions = function;
}

public void changeFamily(ValueChangeEvent event) {
    FacesContext context = FacesContext.getCurrentInstance();
    int value = (Integer) event.getNewValue();
    setFunctions(getFunctions(value));

    context.renderResponse();        
}}

Upvotes: 1

Views: 6404

Answers (1)

ebaxt
ebaxt

Reputation: 8417

I think the problem here is that the getFunctions(int i) takes a parameter. Since it is called by the EL expression below, it should not take a parameter.

 <f:selectItems id="functions" value="#{menuBean.functions}" /> 

Also, the value from the ValueChangeEvent needs to be casted to a String, not an Integer. Not sure from your question if you have wraped the selectItem in a form, if not you have to do that as well. Last thing I can think of is the scope of the backingBean, it needs to survive the postback.

I tried the example below with a session scoped managedBean and JSF 1.2 and it worked:

   <h:form>
        <h:selectOneMenu id="selectFamily"
                         valueChangeListener="#{menuBean.changeFamily}"
                         immediate="true"
                         onchange="submit()">
            <f:selectItems id="familyNames" value="#{menuBean.familyNames}"/>
        </h:selectOneMenu>

        <h:selectOneMenu id="selectFunction" immediate="true">
            <f:selectItems id="functions" value="#{menuBean.functions}"/>
        </h:selectOneMenu>
    </h:form>

public class MenuBean {
    private SelectItem[] familyNames = {
            new SelectItem(1, "Operations"),
            new SelectItem(2, "Special"),
            new SelectItem(3, "Support")};

    public SelectItem[] getFamilyNames() {
        return familyNames;
    }

    private SelectItem[] functions = {new SelectItem("Select Function")};

    private SelectItem[] operationsFunctions = {
            new SelectItem("Air/Ocean Freight"),
            new SelectItem("Customs"),
            new SelectItem("Land Transport"),
            new SelectItem("Logistics/SCM"),
            new SelectItem("Rail Transport"),
            new SelectItem("Special")
    };

    private SelectItem[] specialFunctions = {
            new SelectItem("General Management"),
            new SelectItem("Quality & Processes")
    };

    private SelectItem[] supportFunctions = {
            new SelectItem("Finance/Controlling"),
            new SelectItem("Human Resources"),
            new SelectItem("ICT"),
            new SelectItem("Legal Affairs"),
            new SelectItem("Marketing/Public Relations"),
            new SelectItem("Procurement"),
    };

    public SelectItem[] getFunctions() {
        return functions;
    }

    private void switchSelectedFunctions(int n) {
        if (n == 1) {
            setFunctions(operationsFunctions);
        } else if (n == 2) {
            setFunctions(specialFunctions);
        } else if (n == 3) {
            setFunctions(supportFunctions);
        }
    }

    public void setFunctions(SelectItem[] function) {
        this.functions = function;
    }

    public void changeFamily(ValueChangeEvent event) {
        FacesContext context = FacesContext.getCurrentInstance();
        int value = Integer.valueOf(((String) event.getNewValue()));
        switchSelectedFunctions(value);
        context.renderResponse();
    }
}

Upvotes: 3

Related Questions