Estou com um pequeno problema ao implementar o sistema de validação dos campos do formulário.
É que assim que seleciono um item no primeiro SelectOneMenu de “estados”, ele alimenta corretamente o outro SelectOneMenu de “municípios” (devido ao valueChangeListener), mas já dispara o validador deste segundo componente (validarMunicipio), exibindo a mensagem de erro antes mesmo de submeter o formulário no commandButton no final da página.
Gostaria que esta validação só fosse disparada ao submeter o formulário. O que está errado?
Seguem abaixo os trechos de código envolvidos:
- JSF
(...)
<h:outputLabel value="UF" for="estado" />
<h:selectOneMenu id="estado" valueChangeListener="#{localidadeMB.selecionarEstado}" validator="#{localidadeMB.validarEstado}">
<f:selectItems value="#{localidadeMB.estados}"/>
<a4j:support event="onchange" reRender="municipio" focus="municipio" />
</h:selectOneMenu>
<h:message for="estado" styleClass="mensagemErro"/>
<h:outputLabel value="Município" for="municipio" />
<h:selectOneMenu id="municipio" valueChangeListener="#{localidadeMB.selecionarMunicipio}" validator="#{localidadeMB.validarMunicipio}">
<f:selectItems value="#{localidadeMB.municipios}"/>
</h:selectOneMenu>
<h:message for="municipio" styleClass="mensagemErro"/>
(...)
- managed bean
public List<SelectItem> getEstados(){
List<SelectItem> itens = new ArrayList<SelectItem>();
try{
//cria a opção em branco para as UFs
itens.add(new SelectItem("--"));
for(Estado e : estadoFacade.getEstados()){
itens.add(new SelectItem(e.getUf()));
}
return itens;
} catch (PropertiesFileException e) {
exibeMensagem(e.getMessage());
e.printStackTrace();
return null;
}
}
public List<SelectItem> getMunicipios(){
return this.municipiosPorEstado; ///este objeto é inicializado no construtor
}
public void selecionarEstado(ValueChangeEvent evento){
//cria a primeira opção para a caixa de seleção
municipiosPorEstado.clear();
municipiosPorEstado.add(new SelectItem("-- selecione o município --"));
try{
//popula a lista de seleção de municipios de acordo com a UF selecionada
estado = estadoFacade.getEstado(evento.getNewValue().toString());
//popula a lista de municípios do estado selecionado
for(Municipio m : municipioFacade.getMunicipios(estado)){
municipiosPorEstado.add(new SelectItem(m.getNome()));
}
} catch (PropertiesFileException e) {
exibeMensagem(e.getMessage());
e.printStackTrace();
}
}
public void selecionarMunicipio(ValueChangeEvent evento){
if(!evento.getNewValue().toString().equals("-- selecione o município --")){
//popula coleção de localidades desta UF
getLocalidadePorUF(evento.getNewValue().toString());
//popula a lista de localidades relacionadas e remissivas
for(Localidade l : localidadesPorUF){
localidadesRelacionadas.add(new SelectItem(l.getNome()));
localidadesRemissivas.add(new SelectItem(l.getNome()));
}
}
}
public void validarEstado(FacesContext context, UIComponent componentToValidate, Object value) throws ValidatorException {
if(((String)value).equals("--")){
FacesMessage msg = new FacesMessage("Selecione uma UF");
throw new ValidatorException(msg);
}
}
public void validarMunicipio(FacesContext context, UIComponent componentToValidate, Object value) throws ValidatorException {
if(((String)value).equals("-- selecione o município --")){
FacesMessage msg = new FacesMessage("Selecione um município");
throw new ValidatorException(msg);
}
}