1

In my xhtml page i have two dependant selectOneMenu, with the second one being filled in an ajax call. Here's the jsf code fragment:

   <h:panelGrid columns="2" cellpadding="5">
     <h:outputLabel value="Dirección:" for="direccion"/>
       <p:inputText id="direccion" value="#{datosInstitucion.institucion.direccion}" required="true" label="Dirección"/>
       <h:outputLabel value="Departamento:" for="departamento"/>
       <p:selectOneMenu id="departamento" value="#{datosInstitucion.idDepartamento}" required="true" label="Departamento">
          <f:selectItem itemLabel="Seleccione el departamento" itemValue="#{null}"/>
          <c:forEach items="#{datosInstitucion.departamentos}" var="departamento">
             <f:selectItem itemLabel="#{departamento.nombre}" itemValue="#{departamento.id}"/>
          </c:forEach>
          <f:ajax render="municipio" listener="#{datosInstitucion.cargarMunicipios()}"/>
       </p:selectOneMenu>
       <h:outputLabel value="Municipio:" for="municipio"/>
       <p:selectOneMenu id="municipio" value="#{datosInstitucion.idMunicipio}"                                           required="true" label="Municipio">
          <f:selectItem itemLabel="Seleccione el municipio" itemValue="#{null}"/>
             <c:forEach items="#{datosInstitucion.municipios}" var="municipio">
                <f:selectItem itemLabel="#{municipio.nombre}" itemValue="#{municipio.id}"/>
             </c:forEach>
       </p:selectOneMenu>
   </h:panelGrid>

This fragment of code is inside a primefaces wizard component, so when the 'next' button is pressed a validation error is caused for the second selectOneMenu even when there's a value set.

What could be causing this behavior?

Relevant backing bean code:

@ManagedBean(name = "datosInstitucion")
@ViewScoped
public class DatosInstitucion implements Serializable{

    @EJB
    private Instituciones instituciones;

    @EJB
    private Parametros parametros;

    @Inject
    private Mensajes mensajes;

    private List<Departamento> departamentos;
    private List<Municipio> municipios;
    private Map<Integer, Departamento> mapaDepartamentos;
    private Integer idDepartamento;
    private Integer idMunicipio;

    private Institucion institucion;

    @PostConstruct
    private void inicializar(){
        this.mapaDepartamentos = new HashMap<>();
        this.departamentos = parametros.consultarDepartamentos();
        for(Departamento departamento : departamentos){
            this.mapaDepartamentos.put(departamento.getId(), departamento);
        }
        this.prepararInstitucion();
    }

    private void prepararInstitucion(){
        this.institucion = new Institucion();
        this.institucion.setResponsable(new Persona());
    }

    public Institucion getInstitucion() {
        return institucion;
    }

    public List<Departamento> getDepartamentos(){
        return departamentos;
    }

    public TipoIdentificacion[] getTiposIdentificacion(){
        return TipoIdentificacion.deResponsables();
    }

    public Integer getIdDepartamento() {
        return idDepartamento;
    }

    public void setIdDepartamento(Integer idDepartamento) {
        this.idDepartamento = idDepartamento;
    }

    public Integer getIdMunicipio() {
        return idMunicipio;
    }

    public void setIdMunicipio(Integer idMunicipio) {
        this.idMunicipio = idMunicipio;
    }

    public void cargarMunicipios(){
        idMunicipio = null;
        if(idDepartamento != null){
            this.municipios = mapaDepartamentos.get(idDepartamento).getMunicipios();
        }else{
            this.municipios = Collections.emptyList();
        }
    }

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

    public void confirmar(){
        this.instituciones.guardar(institucion);
        this.mensajes.exito("La institución ha sido registrada en el sistema");
        this.prepararInstitucion();
    }
}
fareed
  • 3,034
  • 6
  • 37
  • 65
fturizo
  • 225
  • 4
  • 13

1 Answers1

1

This is because you are using JSTL <c:foreach> with JSF. The life cycle of JSTL vs JSF matters. JSTL is executed when the view is being built, while JSF is executed when the view is being rendered. The two do not work in synch with each other. In your case, you need to use <f:selectItems> instead of <c:foreach>

Replace:

<c:forEach items="#{datosInstitucion.municipios}" var="municipio">
      <f:selectItem itemLabel="#{municipio.nombre}" itemValue="#{municipio.id}"/>
</c:forEach>

with:

<f:selectItems value="#{datosInstitucion.municipios}" 
    var="municipio" itemLabel="#{municipio.nombre}" 
    itemValue="#{municipio.id}"/>

For more reading, I suggest you to read the following answer

Community
  • 1
  • 1
fareed
  • 3,034
  • 6
  • 37
  • 65