[Resolvido] JSF2 SelectOneMenu não dispara ValueChangeListener (Primefaces)

Caros colegas,
Gostaria de saber se alguém já passou pelo mesmo problema e conseguiu fazer funcionar? Trata-se de uma combinação simples de 2 selects. Busquei incansavelmente algum exemplo, entretanto não consegui encontrar (com jsf 2). No forum existem bastante tópicos mas não consegui encontrar nenhum que funcionasse.

O atributo ‘valueChangeListener’ do componente h:selectOneMenu, não chega nem a chamar o método ufChangeListener(ValueChangeEvent e) no bean. Deve haver algum problema no javascript do framework.

pagina.xhtml

    <h:form id="form-cidades-uf">
    
    <h:selectOneMenu id="sob-ufs"
                     value="#{cidadeUFComboBean.selecUF}"
                     onchange="submit()"
                     immediate="true"
		     valueChangeListener="#{cidadeUFComboBean.ufChangeListener}">
        <f:selectItem itemLabel="-- Selecione a uf -- " itemValue="Nenhuma"/>    
        <f:selectItems value="#{cidadeUFComboBean.ufs}" var="u" itemValue="#{u}" itemLabel="#{u.sigla}"/>
        <f:ajax event="change" render="sob-cidades @form"/>

        
    </h:selectOneMenu>
        
    <h:selectOneMenu id="sob-cidades"
                     value="#{cidadeUFComboBean.selecCidade}" >
        <f:selectItem itemLabel="-- Selecione a cidade -- " itemValue="Nenhuma"/>  
        <f:selectItems value="#{cidadeUFComboBean.cidades}" var="c" itemValue="#{c}" itemLabel="#{c.nome}"/>
        <f:ajax />
    </h:selectOneMenu>  
     
    </h:form>

O Bean:

    // Cidade selecionada
    private EnderecoCidade selecCidade;

    public EnderecoCidade getSelecCidade() {
        return selecCidade;
    }
    public void setSelecCidade(EnderecoCidade selecCidade) {
        this.selecCidade = selecCidade;
    }
    
    // Cidades do estado selecionado
    private List<EnderecoCidade> cidades;
    
    public List<EnderecoCidade> getCidades() {
        lookup.getCidDao().list(selecUF);
        return cidades;
    }
    
    // UF selecionada
    private EnderecoUF selecUF;
    
    public EnderecoUF getSelecUF() {
        return selecUF;
    }
    public void setSelecUF(EnderecoUF selecUF) {
        this.selecUF = selecUF;
    }
    
    // UFs
    private List<EnderecoUF> ufs;
    
    public List<EnderecoUF> getUfs() {
        if(ufs==null){
            ufs = lookup.getUfDao().list();
        }
        return ufs;
    }
    
    public void ufChangeListener(ValueChangeEvent e){
        selecUF = (EnderecoUF) e.getNewValue();
        cidades = getCidades();
        
        System.out.println("ufChangeListener: uf="+selecUF.getSigla()+", listou "+cidades.size()+" cidades...");
    }

Desde já agradeço,

Um grande abraço,

alguma exception é disparada? Já debugou para saber por onde está passando?

Obrigado André,

Nenhuma Exception é lançada, o listener não é nem chamado, simplesmente ‘ValueChangeListener’ não dispara um evento quando a mudança de valor acontece.

Tenho logs em todo o código, que mostram que o metodo não foi chamado.

Um grande abraço,

Olha, existem componentes que podem te ajudar com esse problema, o que te facilitaria em 1000% o trabalho e te salvaria muita “manualidade”. O primefaces no momento é a ferramenta mais estável para se trabalhar com JSF2, e ele tem um componente que te facilita com aninhamento de combos.

o link que te passei acima te leva para este componente, que é o ajax event, que te ajudará com esses problemas.


voltando ao seu problema sem primefaces, tente fazer o seguinte, chame um onSelect que invoque esta ação, assim você conseguirá fazer a alteração. Não jogue no valueChangeListener, faça onchange ou onclick, se ainda assim o erro persistir, ele vai jogar uma exceção pra ti.

Ok! obrigado! Já estou utilizando o Primefaces em diversas outras partes do projeto.

Estou tentando usar o ajax, do Primefaces, tb. para este item em específico.

Um grande abraço!

pra tefacilitar mais então:

<h:selectOneMenu id="sob-ufs"  
                 value="#{cidadeUFComboBean.selecUF}"  
                 onchange="submit()"  
                 immediate="true"  
   valueChangeListener="#{cidadeUFComboBean.ufChangeListener}">  
    <f:selectItem itemLabel="-- Selecione a uf -- " itemValue="Nenhuma"/>      
    <f:selectItems value="#{cidadeUFComboBean.ufs}" var="u" itemValue="#{u}" itemLabel="#{u.sigla}"/>  

    <p:ajax event="change" update="sob-cidades" />      //aqui

</h:selectOneMenu> 

<h:selectOneMenu id="sob-cidades"  
                 value="#{cidadeUFComboBean.selecCidade}" >  
    <f:selectItem itemLabel="-- Selecione a cidade -- " itemValue="Nenhuma"/>    
    <f:selectItems value="#{cidadeUFComboBean.cidades}" var="c" itemValue="#{c}" itemLabel="#{c.nome}"/>  
    <f:ajax />  
</h:selectOneMenu> 

Obrigado André!

Apenas acrescentando a tag ‘<p:ajax />’ não funcionou, mas peguei este mesmo exemplo do site do Primefaces e funcionou, agora vou adapta-lo a meu projeto. Acho que por que, o exemplo do site está usando Strings diretamente ao invés de objetos.

Acho que vai ser por aí mesmo.

Só achei estranho o ‘valueChangeListener’ não disparar o evento. Se por acaso tiver um exemplo de selects aninhados com ‘valueChangeListener’ em JSF2/Facelets, ou se alguém tiver por favor envie.

Muito obrigado pelo apoio amigo,
Um grande abraço,

Opa! Pra quem quiser, coloquei aqui o código do combo funcionando com JSF2 e Primefaces:
http://www.codesample.co/2011/08/combo-cidade-uf-com-primefaces-e-jsf-2/

Um grande abraço a todos!

Eu quero usar o p:selectOneMenu, do próprio Primefaces, para manter a uniformidade visual dos componentes, mas nada do que eu tentei funcionou.

Se faço da seguinte forma:

*.xhtml

...

<p:selectOneMenu id="cmbEstadoPesquisa"	value="#{cidadeBean.estado.codigo}"												
	label="#{msg.lblEstado}" style="width: 300px;">								 
	<f:selectItems value="#{cidadeBean.itensEstados}"/>
	<p:ajax listener="#{cidadeBean.cmbEstadoChange}" update="tblCidade"/>
</p:selectOneMenu>											

...

Bean

[code]public void cmbEstadoChange(AjaxBehaviorEvent event) {

try {

        FacesContext context = FacesContext.getCurrentInstance();
	String idEstado = event.getComponent().getAttributes().get("value").toString();


[/code]

O valor de idEstado é sempre o valor que estava selecionado antes (velho) e não o novo valor. O mesmo ocorre com o valorde cidadeBean.estado.codigo, que não é atualizado com o valor atual.

Simplesmente não sei como fazer isso usando somente os componentes do Primefaces. Estou quase voltando ao Richfaces.

Descobri o problema!

Se eu atribuo o valor do componente a um atributo de uma variável de referência do bean, como em:

cidadeBean.estado.codigo

Não funciona. Se eu atribuo a um atributo direto do bean, como em

cidadeBean.codigoEstado

Funciona!

Fica a dica!

Acreditem se quiserem, mas era o nome do meu metodo. Tive o mesmo problema
BRincadeira!