After requesting AJAX input no arrow value to Managedbean?

Asked

Viewed 584 times

1

I’m building an address registration form and implemented the State and City combos respectively. They work as usual, with the city combo being filled in according to the value selected by the state combo.

I read a tutorial on the Internet about how to implement this functionality, however I am having a very annoying problem regarding mandatory fields and attribution of input values to Managedbean. This is because the ajax event responsible for loading the city combo based on the state value works, however, after giving a Ubmit in the registration form the city value is not set in the bean and the JSF issues a "Required field".

I’ve been looking for the cause for a while... but I haven’t found it yet.

My implementation is as follows:

xhtml address.

<f:view>
    <p:fieldset legend="Endereco">
        <h:panelGrid columns="2">
            <h:panelGrid columns="2">
                <p:outputLabel value="Logradouro: " id="lblLogradouro"
                    for="txtLogradouro" />
                <p:inputText value="#{enderecoBean.endereco.logradouro}"
                    id="txtLogradouro" style="width:435px;" required="true"
                    requiredMessage="É necessário preencher o campo Logradouro!" />
            </h:panelGrid>

            <h:panelGrid columns="2">
                <p:outputLabel value="Numero: " id="lblNumero" for="txtNumero" />
                <p:inputText value="#{enderecoBean.endereco.numero}" id="txtNumero"
                    required="true"
                    requiredMessage="É necessário preencher o campo Número!" />
            </h:panelGrid>

            <h:panelGrid columns="4">
                <p:outputLabel value="Bairro: " id="lblBairro" for="txtBairro" />
                <p:inputText value="#{enderecoBean.endereco.bairro}" id="txtBairro"
                    required="true"
                    requiredMessage="É necessário preencher o campo Bairro!" />

                <p:outputLabel value="Complemento: " id="lblComplemento"
                    for="txtComplemento" />
                <p:inputText value="#{enderecoBean.endereco.complemento}"
                    id="txtComplemento" />
            </h:panelGrid>

            <h:panelGrid columns="2">
                <p:outputLabel value="Cep " id="lblCep" for="txtCep" />
                <p:inputText value="#{enderecoBean.endereco.cep}" id="txtCep"
                    required="true"
                    requiredMessage="É necessário preencher o campo Cep!" />
            </h:panelGrid>

            <h:panelGrid columns="4">
                <p:outputLabel value="Estado: " id="lblEstado" for="estado" />
                <p:selectOneMenu id="estado" value="#{enderecoBean.estadoEscolhido}"
                    converter="estadoConverter" required="true">
                    <f:selectItem itemLabel="Selecione" />
                    <f:selectItems value="#{enderecoBean.listaEstados}" var="e"
                        itemValue="#{e}" itemLabel="#{e.sigla}" />
                    <f:ajax render="cidade" event="change"
                        listener="#{enderecoBean.alterarCidadesPorEstado}" />
                </p:selectOneMenu>

                <p:outputLabel value="Cidade: " for="cidade" id="lblCidade" />
                <p:selectOneMenu id="cidade" value="#{enderecoBean.cidadeEscolhida}"
                    converter="cidadeConverter" required="true">
                    <f:selectItem itemLabel="Selecione" />
                    <f:selectItems value="#{enderecoBean.listaCidades}" var="c"
                        itemValue="#{c}" itemLabel="#{c.nomeCidade}" />
                </p:selectOneMenu>
            </h:panelGrid>
        </h:panelGrid>
    </p:fieldset>
</f:view>

Enderecobean.java

package br.com.biblioteca.bean;

import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;
import br.com.biblioteca.dao.CidadeDAO;
import br.com.biblioteca.dao.EstadoDAO;
import br.com.biblioteca.model.Cidade;
import br.com.biblioteca.model.Endereco;
import br.com.biblioteca.model.Estado;

@ManagedBean
@ViewScoped
public class EnderecoBean {

    private Endereco endereco;
    private Estado estadoEscolhido;
    private Cidade cidadeEscolhida;
    private List<Estado> listaEstados;
    private List<Cidade> listaCidades;
    private CidadeDAO cidadeDao;

    public EnderecoBean(){
        this.endereco = new Endereco();
        cidadeDao = new CidadeDAO();
        EstadoDAO dao = new EstadoDAO();
        listaEstados = dao.listar();
    }

    public void setEndereco(Endereco endereco){
        this.endereco = endereco;
    }

    public Endereco getEndereco(){
        return this.endereco;
    }

    public Estado getEstadoEscolhido() {
        return estadoEscolhido;
    }

    public void setEstadoEscolhido(Estado estadoEscolhido) {
        this.estadoEscolhido = estadoEscolhido;
    }

    public Cidade getCidadeEscolhida() {
        return cidadeEscolhida;
    }

    public void setCidadeEscolhida(Cidade cidadeEscolhida) {
        this.cidadeEscolhida = cidadeEscolhida;
    }

    public List<Estado> getListaEstados() {
        return listaEstados;
    }

    public void setListaEstados(List<Estado> listaEstados) {
        this.listaEstados = listaEstados;
    }

    public List<Cidade> getListaCidades() {
        return listaCidades;
    }

    public void setListaCidades(List<Cidade> listaCidades) {
        this.listaCidades = listaCidades;
    }


    public void alterarCidadesPorEstado(final AjaxBehaviorEvent event){
        if(estadoEscolhido == null)
            return;     

        try{
            this.listaCidades = cidadeDao.cidadeByEstado(estadoEscolhido);
        }catch(Exception e){
            e.printStackTrace();
            FacesMessage msgErro = new FacesMessage(FacesMessage.SEVERITY_ERROR, "ERRO","Falha ao buscar as cidades atreladas ao estado selecionado!");
            FacesContext.getCurrentInstance().addMessage(null, msgErro);
        }
    }
}

Estadoconverter.java

package br.com.biblioteca.converter;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;

import br.com.biblioteca.dao.EstadoDAO;
import br.com.biblioteca.model.Estado;

@FacesConverter(value="estadoConverter")
public class EstadoConverter implements Converter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if(value != null || !value.isEmpty()){
            EstadoDAO estadoDao = new EstadoDAO();
            Estado estado = estadoDao.buscar(Integer.valueOf(value));
            return estado;
        }
        return null;
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if(value instanceof Estado){
            Estado estado = (Estado)value;
            return String.valueOf(estado.getIdEstado());
        }
        return "";
    }

}

Citadeconverter.java

package br.com.biblioteca.converter;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;

import br.com.biblioteca.dao.CidadeDAO;
import br.com.biblioteca.model.Cidade;

@FacesConverter(value = "cidadeConverter")
public class CidadeConverter implements Converter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (value != null && !value.equals("")) {
            CidadeDAO dao = new CidadeDAO();
            return dao.buscar(Integer.valueOf(value));
        }
        return null;
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if (value instanceof Cidade) {
            Cidade municipio = (Cidade) value;
            return String.valueOf(municipio.getIdCidade());
        }
        return "";
    }

}

Any idea?

1 answer

1


This is a Primefaces bug that can be fixed easily by placing an element that involves the component that will be updated. Follows gernérico example:

<p:selectOneMenu>
    <p:ajax update="panel-pai" />
</p:selectOneMenu>

<h:panelGroup id="panel-pai">
    <p:selectOneMenu id="listaSelecao" />
</h:panelGroup>

If you’re using a list that depends on another, don’t forget to update the element itself:

<h:panelGroup id="panel-cidade">
    <p:selectOneMenu id="cidade">
        <p:ajax update="panel-cidade panel-estado" />
    </p:selectOneMenu>
</h:panelGroup>

<h:panelGroup id="panel-estado">
    <p:selectOneMenu id="estado" />
</h:panelGroup>

Or else place both components within just one parent element:

<h:panelGroup id="panel-endereco">
    <p:selectOneMenu id="cidade">
        <p:ajax update="panel-endereco" />
    </p:selectOneMenu>

    <p:selectOneMenu id="estado" />
</h:panelGroup>

For you to make this update you must:

  • Send your managedBean the selection of the State
  • Via the selected Status update the list of Cities
  • Update the elements involving selectOneMenus correspondent

Applied to your code:

<p:panelGrid id="panel-pai" columns="4">
    <p:outputLabel value="Estado: " id="lblEstado" for="estado" />
    <p:selectOneMenu id="estado" value="#{enderecoBean.estadoEscolhido}"
       converter="estadoConverter" required="true">
        <f:selectItem itemLabel="Selecione" />
        <f:selectItems value="#{enderecoBean.listaEstados}" var="e"
                       itemValue="#{e}" itemLabel="#{e.sigla}" />
        <p:ajax update="panel-pai" event="change"
           listener="#{enderecoBean.alterarCidadesPorEstado}" />
    </p:selectOneMenu>

    <p:outputLabel value="Cidade: " for="cidade" id="lblCidade" />
    <p:selectOneMenu id="cidade" value="#{enderecoBean.cidadeEscolhida}"
       converter="cidadeConverter" required="true">
        <f:selectItem itemLabel="Selecione" />
        <f:selectItems value="#{enderecoBean.listaCidades}" var="c"
           itemValue="#{c}" itemLabel="#{c.nomeCidade}" />
    </p:selectOneMenu>
</p:panelGrid>
  • A id to the panelGrid that involves your selectOneMenus
  • Your update should be on top of that id which encompasses the selectOneMenus at all times
  • I recommend moving <f:ajax render="panelX"/> for <p:ajax update="panelX"/>
  • Your h:panelGrid can change p:panelGrid Primefaces native if you prefer

I recommend using as many native Primefaces tags as JSTL tags.


One more remark, your managedBean should be serialized. Example:

public class EnderecoBean implements Serializable {
    private static final long serialVersionUID = 1L;
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.