I am building an address registration form and I have implemented the combos for State and City respectively. They work in the usual way, with the combo of the city being filled according to the value selected by the state combo.
I have read a tutorial on how to implement this functionality, however I am having a very annoying problem regarding the mandatory fields and value assignment of the inputs to the ManagedBean. This is because the ajax event responsible for loading the city combo based on the state value works, however, after giving a submit in the registration form the city value is not set in the bean and JSF spits out a "Required field" .
I'm trying to find the cause ... but I have not found it yet.
My implementation is as follows:
address.xhtml
<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);
}
}
}
StatusConverter.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 "";
}
}
CityConverter.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 ideas?