How to update a selectonemenu depending on other one selected value?
Asked Answered
B

4

6

I've been having a trouble trying to make my selectOneMenu content, depend on the value selected on the other. The content from the first one comes from a table in my DataBase and works perfectly, but the second one is supposed to come from another table, but I can't make it work. Here is my index.html, where I'm just trying to prove how this works:


        <h:outputLabel value="Estado" styleClass="requiredLbl"/>
        <p:selectOneMenu id="Estado" value="#{beanInscripcion.id_estado}" valueChangeListener="#{beanInscripcion.buscarMunicipios(event)}" >  
            <f:selectItem itemLabel="Elegir Estado" itemValue="" />
            <f:selectItems value="#{beanInscripcion.estados}"  
                           var="edo" itemLabel="#{edo.nombre_estado}" itemValue="#{edo.id_estado}" />  
            <p:ajax update="Municipio"  listener="#{beanInscripcion.buscarMunicipios(event)}" />
        </p:selectOneMenu> 
        <p:separator /> 
        <h:outputLabel value="Municipio" styleClass="requiredLbl"/>
        <p:selectOneMenu id="Municipio" value="municipio">  
            <f:selectItems value="#{beanInscripcion.municipios}"  
                           var="mun" itemLabel="#{mun.nombre_municipio}" itemValue="#{mun.nombre_municipio}" />  
        </p:selectOneMenu>

And here is the section of my Bean where I'm supposed to get the content for the second menu:


@ManagedBean(name = "beanInscripcion")
@ViewScoped
public class BeanInscripcion implements Serializable {

    static String strURL;
    private List<Estado> estados; 
    private List<Municipio> municipios;
    private int id_estado;
    public BeanInscripcion() throws SQLException{
            estados = new ArrayList<Estado>();
            buscarEstados();
    }

    public void buscarEstados() throws SQLException {
        Connection connection = getConnection();
        Statement statement = connection.createStatement();
        ResultSet result = statement.executeQuery("SELECT * FROM estado");
        result.beforeFirst();
        while (result.next()) {
            Estado estado = new Estado();
            estado.setId_estado(result.getInt("id_estado"));
            estado.setNombre_estado(result.getString("nombre_estado"));
            estados.add(estado);
        }
    }

    public void buscarMunicipios() throws SQLException {
        Connection connection = getConnection();
        Statement statement = connection.createStatement();
        ResultSet result = statement.executeQuery("SELECT id_municipio, nombre_municipio FROM municipio WHERE Estado_id_estado = '" + id_estado + "'");
        result.beforeFirst();
        while (result.next()) {
            Municipio municipio = new Municipio();
            municipio.setId_municipio(result.getInt("id_municipio"));
            municipio.setNombre_municipio(result.getString("nombre_municipio"));
            municipios.add(municipio);
        }
    }

    public Connection getConnection() {
        try {
            strURL = "jdbc:mysql://localhost:3306/mydb";
            Class.forName("com.mysql.jdbc.Driver");
            return DriverManager.getConnection(strURL, "root", "root");
        } catch (SQLException ex) {
            return null;
        } catch (ClassNotFoundException ex) {
            return null;
        }
    }

    public List<Estado> getEstados() {
        return estados;
    }

    public void setEstados(List<Estado> estados) {
        this.estados = estados;
    }

    public List<Municipio> getMunicipios() {
        return municipios;
    }

    public void setMunicipios(List<Municipio> municipios) {
        this.municipios = municipios;
    }

    public int getId_estado() {
        return id_estado;
    }

    public void setId_estado(int id_estado) {
        this.id_estado = id_estado;
    }
}

I've been working on this for hours and still nothing, I'm really in a hurry here, so I'd appreciate if you give me some help here. Thx a lot for your attention :D

Backache answered 12/11, 2012 at 5:36 Comment(0)
E
6
  1. value="municipio" in <p:selectOneMenu id="Municipio" value="municipio"> means that the value in that dropdown will never change as you've effectively hardcoded the value on that field to always be municipio (and even that will fail conversion). The value attribute should be bound to a backing bean variable as in

      <p:selectOneMenu id="Municipio" value="#{beanInscripcion.municipio}" >  
        <f:selectItems value="#{beanInscripcion.municipios}"  
                       var="mun" itemLabel="#{mun.nombre_municipio}" itemValue="#{mun.nombre_municipio}" />  
    </p:selectOneMenu>
    

    and in your backing bean, have

       Municipio municipio;
      //getter and setter
    
  2. Remove the parameter event from <p:ajax update="Municipio" listener="#{beanInscripcion.buscarMunicipios(event)}" />. It should be

    <p:ajax update="Municipio"  listener="#{beanInscripcion.buscarMunicipios}" />
    
  3. Remove valueChangeListener="#{beanInscripcion.buscarMunicipios(event)}". It's unnecessary because you already have a <p:ajax/> event defined

  4. You will eventually run into problems submitting that form because you haven't created a JSF Converter for that Municipio custom type. It's mandatory if you're using anything other than String types in your select components. See a short intro to converters/converting here

Entertaining answered 12/11, 2012 at 6:18 Comment(0)
I
6

I am using Primefaces and this is pretty simple. I have 2 seleceOneMenus, one for subjects (the parent one) and another one for Topics (the child one.).

<h:selectOneMenu id="subject" value="#{QuestionsMB.selectedSubjectId}" var="selectedSubject">  
                <f:selectItem itemLabel="Select Subject" noSelectionOption="true" />
                <f:selectItems value="#{SubjectsMB.subjectsList}" var="selectedSubject" itemValue="#{selectedSubject.id}" itemLabel="#{selectedSubject.subjectName}" />
                <p:ajax update="topic" />
            </h:selectOneMenu>


            <h:selectOneMenu id="topic" value="#{QuestionsMB.selectedTopicId}" var="selectedTopic">  
                <f:selectItem itemLabel="Select Topic" noSelectionOption="true" />
                <f:selectItems value="#{TopicsMB.getTopicsListBySubjectId(QuestionsMB.selectedSubjectId)}" var="selectedTopic" itemValue="#{selectedTopic.id}" itemLabel="#{selectedTopic.topicName}" />
            </h:selectOneMenu>

Just notice, that when subject selectonemenu changes, then the topics menu change according to subject ID. I had create a simple function inside Topics Managed Bean (the managed bean for the child selectonemenu ) by editing the hibernate getList() function like as under:

public List<Topics> getTopicsListBySubjectId(String subjectID) 
    {
        Topics topic = new Topics();
        List<Topics> TopicsList = new ArrayList<Topics>();

        if(subjectID.length() != 0)
        {
            topic.setSubjectId(Integer.parseInt(subjectID));
            TopicsList = getTopicsService().getTopicsBySubjectId(topic);
        }
        else
        {   
            TopicsList.addAll(getTopicsService().getTopics());
        }
        return TopicsList;
    }

and things worked like a charm.... :)

Isolationist answered 22/1, 2013 at 18:0 Comment(0)
A
0

I know a solution for RichFaces, I'm pretty sure it will works for PrimeFaces as components are almost the same :

http://showcase.richfaces.org/richfaces/component-sample.jsf?demo=ajax&sample=selectsUpdates&skin=blueSky

EDIT : Here is the translation applied to your code :

<h:outputLabel value="Estado" styleClass="requiredLbl"/>
<p:selectOneMenu id="Estado" value="#{beanInscripcion.id_estado}" valueChangeListener="#{beanInscripcion.buscarMunicipios(event)}" >  
    <f:selectItem itemLabel="Elegir Estado" itemValue="" />
    <f:selectItems value="#{beanInscripcion.estados}" var="edo" itemLabel="#{edo.nombre_estado}" itemValue="#{edo.id_estado}" />  
    <p:ajax update="second" process="@this" listener="#{beanInscripcion.buscarMunicipios(event)}" />
</p:selectOneMenu>
<p:separator />
<p:outputPanel id="second">
    <h:outputLabel rendered="#{not empty beanInscripcion.id_estado}" value="Municipio" styleClass="requiredLbl"/>
    <p:selectOneMenu rendered="#{not empty beanInscripcion.id_estado}" id="Municipio" value="municipio">  
        <f:selectItems value="#{beanInscripcion.municipios}" var="mun" itemLabel="#{mun.nombre_municipio}" itemValue="#{mun.nombre_municipio}" />  
    </p:selectOneMenu>
</p:outputPanel>

And for the bean :

@ManagedBean(name = "beanInscripcion") @RequestScoped public class BeanInscripcion implements Serializable {

static String strURL;
private List<Estado> estados; 
private List<Municipio> municipios;
private int id_estado;
public BeanInscripcion() throws SQLException{
        estados = new ArrayList<Estado>();
        buscarEstados();
}

public void buscarEstados() throws SQLException {
    Connection connection = getConnection();
    Statement statement = connection.createStatement();
    ResultSet result = statement.executeQuery("SELECT * FROM estado");
    result.beforeFirst();
    while (result.next()) {
        Estado estado = new Estado();
        estado.setId_estado(result.getInt("id_estado"));
        estado.setNombre_estado(result.getString("nombre_estado"));
        estados.add(estado);
    }
}

public void buscarMunicipios() throws SQLException {
    Connection connection = getConnection();
    Statement statement = connection.createStatement();
    ResultSet result = statement.executeQuery("SELECT id_municipio, nombre_municipio FROM municipio WHERE Estado_id_estado = '" + id_estado + "'");
    result.beforeFirst();
    while (result.next()) {
        Municipio municipio = new Municipio();
        municipio.setId_municipio(result.getInt("id_municipio"));
        municipio.setNombre_municipio(result.getString("nombre_municipio"));
        municipios.add(municipio);
    }
}

public Connection getConnection() {
    try {
        strURL = "jdbc:mysql://localhost:3306/mydb";
        Class.forName("com.mysql.jdbc.Driver");
        return DriverManager.getConnection(strURL, "root", "root");
    } catch (SQLException ex) {
        return null;
    } catch (ClassNotFoundException ex) {
        return null;
    }
}

public List<Estado> getEstados() {
    return estados;
}

public void setEstados(List<Estado> estados) {
    this.estados = estados;
}

public List<Municipio> getMunicipios() {
    return municipios;
}

public void setMunicipios(List<Municipio> municipios) {
    this.municipios = municipios;
}

public int getId_estado() {
    return id_estado;
}

public void setId_estado(int id_estado) {
    this.id_estado = id_estado;
}

}

Hope it will work since it is not tested!

Ariellearies answered 12/11, 2012 at 5:45 Comment(3)
ok, i just tried that, but wont work since i dont have the same properties in primefaces elements, my <p:ajax> tag doesnt have a "render" property or an "execute" one, so i cant use this, but i really apreciate your help, its better than nothing :PBackache
The PrimeFaces equivalent for render is update, the equivalent of execute is process. Actually RichFaces follow more JSF standards ie f:ajax.Ariellearies
Please add some more explanation to your solution for the OP. You just gave him a linkEntertaining
I
0

It is just example. Try to reference for your program.

example.xhtml

        <p:selectOneMenu value="#{SelectOneMenuBean.selectedValue}" 
                         style="width:195px;" required="true" id="countryMenu">
            <p:ajax update="cityMenu"/>
            <f:selectItems value="#{SelectOneMenuBean.countries}"/>
        </p:selectOneMenu>
        <p:selectOneMenu style="width:195px;" required="true" id="cityMenu">
            <f:selectItems value="#{SelectOneMenuBean.cities}"/>
        </p:selectOneMenu>

SelectOneMenuBean.java

@ManagedBean(name="SelectOneMenuBean")
public class SelectOneMenuBean {
    private String selectedValue;

    public String getSelectedValue() {
        return selectedValue;
    }

    public void setSelectedValue(String selectedValue) {
        this.selectedValue = selectedValue;
    }

    public String[] getCountries() {
        return new String[] {"AAA", "BBB", "CCC", "DDD"};
    }

    public String[] getCities() {
        if(selectedValue != null && selectedValue.equals("AAA")) {
            return new String[] {"City_1 of AAA", "City_2 of AAA", "City_3 of AAA"};
        } else if(selectedValue != null && selectedValue.equals("BBB")) {
            return new String[] {"City_1 of BBB", "City_2 of BBB", "City_3 of BBB"};
        } else if(selectedValue != null && selectedValue.equals("CCC")) {
            return new String[] {"City_1 of CCC", "City_2 of CCC", "City_3 of CCC"};
        } else if(selectedValue != null && selectedValue.equals("CCC")) {
            return new String[] {"City_1 of CCC", "City_2 of CCC", "City_3 of CCC"};
        } 
        return new String[] {"No City"};
    }
}
Intelligentsia answered 12/11, 2012 at 6:17 Comment(2)
im trying your example with my own code modifications and im not pretty sure of what scope to use, which one will you recommend me?Backache
lol, i got a new problem, i sticked to your example and tried to implement to mine but for some reason the second <selectOneMenu> disappears instead of showing the new contentBackache

© 2022 - 2024 — McMap. All rights reserved.