Problema com a4j:support ajaxSingle="true"

Bom pessoal, Estou com o seguinte problema:

Estou utilizando uma suggestionbox para retornar uma lista de objetos pesquisados no banco através de uma função que executa a HQL Ao selecionar o objeto que o usuario deseja, ele enviará o código do objeto para o campo ‘codigo’. Dentro do campo código há um a4j:support com event=“onblue” para que, ao sair do foco do campo ‘codigo’ ele realiza a busca da descrição do objeto através do código.

Porém, o suggestionbox não funciona, ou nao consegue carregar o campo ‘codigo’ se eu nao colocar o atributo ajaxSingle=“true”. O mesmo acontece com no campo ‘codigo’ ao buscar a descrição do objeto: ele não consegue carregar sem que haja o atributo ajaxSingle=“true”.

O problema é o seguinte, ao colocar o ajaxSingle=“true”, quando o ajax é executado, meus outros campos de entrada(h:InputText) perdem os valores digitados.

Alguem sabe o que está acontecendo?

Seque o código:

SuggestionBox:

<rich:suggestionbox for="descNaturezaIn" suggestionAction="#{bRLiquidacoes.autoCompletaNatureza}" var="result" 
                                    width="325" id="sugNatureza" minChars="0" nothingLabel="Sem Resultados"
                                    fetchValue="#{result.descricao}">                                                   
                    <h:column id="col1">                                                                      
                        <h:outputText id="out11" value="#{result.codigo}"/>
                    </h:column>
                    <h:column id="col2">                        
                        <h:outputText id="out12" value="#{result.descricao}"/>
                    </h:column> 

                       <a4j:support id="a4j5" focus="codNaturezaIn" event="onselect" reRender="codNaturezaIn, descNaturezaIn" ajaxSingle="true">
                           <f:setPropertyActionListener value="#{result.codigo}" target="#{bRLiquidacoes.codNat}"/>
                    </a4j:support>                                        
</rich:suggestionbox>

Campo código:

<h:inputText id="codNaturezaIn" size="8" binding="#{bRLiquidacoes.natIn}">
           <a4j:support id="a4j3" event="onblur" action="#{bRLiquidacoes.buscaNatureza}" reRender="descNaturezaIn, codNaturezaIn, sugNatureza" ajaxSingle="true"/>
 </h:inputText>
                           <f:setPropertyActionListener value="#{result.codigo}" target="#{bRLiquidacoes.codNat}"/>
                    </a4j:support>                                        
</rich:suggestionbox>

Editei o codigo do Campo. Estava com 3 linhas a mais.

[quote=max.analista]Bom pessoal, Estou com o seguinte problema:

Estou utilizando uma suggestionbox para retornar uma lista de objetos pesquisados no banco através de uma função que executa a HQL Ao selecionar o objeto que o usuario deseja, ele enviará o código do objeto para o campo ‘codigo’. Dentro do campo código há um a4j:support com event=“onblue” para que, ao sair do foco do campo ‘codigo’ ele realiza a busca da descrição do objeto através do código.

Porém, o suggestionbox não funciona, ou nao consegue carregar o campo ‘codigo’ se eu nao colocar o atributo ajaxSingle=“true”. O mesmo acontece com no campo ‘codigo’ ao buscar a descrição do objeto: ele não consegue carregar sem que haja o atributo ajaxSingle=“true”.

O problema é o seguinte, ao colocar o ajaxSingle=“true”, quando o ajax é executado, meus outros campos de entrada(h:InputText) perdem os valores digitados.

Alguem sabe o que está acontecendo?

Seque o código:

SuggestionBox:

<rich:suggestionbox for="descNaturezaIn" suggestionAction="#{bRLiquidacoes.autoCompletaNatureza}" var="result" 
                                    width="325" id="sugNatureza" minChars="0" nothingLabel="Sem Resultados"
                                    fetchValue="#{result.descricao}">                                                   
                    <h:column id="col1">                                                                      
                        <h:outputText id="out11" value="#{result.codigo}"/>
                    </h:column>
                    <h:column id="col2">                        
                        <h:outputText id="out12" value="#{result.descricao}"/>
                    </h:column> 

                       <a4j:support id="a4j5" focus="codNaturezaIn" event="onselect" reRender="codNaturezaIn, descNaturezaIn" ajaxSingle="true">
                           <f:setPropertyActionListener value="#{result.codigo}" target="#{bRLiquidacoes.codNat}"/>
                    </a4j:support>                                        
</rich:suggestionbox>

Campo código: *Editado

<h:inputText id="codNaturezaIn" size="8" binding="#{bRLiquidacoes.natIn}"> <a4j:support id="a4j3" event="onblur" action="#{bRLiquidacoes.buscaNatureza}" reRender="descNaturezaIn, codNaturezaIn, sugNatureza" ajaxSingle="true"/> </h:inputText> [/quote]

o que acontece é que quando você envia uma requisição ajax com ajaxSingle, ele envia somente esse campo do formulário, não o formulário todo.

E quando a requisição volta, se o seu bean tiver escopo de request, ele perderá o valor das outras variáveis, menos essa que veio agora.

se você der um reRender em outros campos, como o bean está vazio seus campos vão perder os dados…

Pelo menos é isso que eu acho que é hehehe

edit: claro que tudo depende do que a sua action está fazendo também…

Opa, bom dia Max.

Como nosso amigo digaoneves falou … Quando você utiliza o ajaxSingle, você estará submetendo somente aquele componente. Para enviar os outros componentes da tela (h:inputText) você deverá utilizar o atributo process.

<a4j:support process="ids dos componentes que deverao ser processados" /> ...

ou

limitar a renderização dos componentes a sua lista de reRender, utilizando o atributo limitToList. Assim:

<a4j:support reRender="lista de reRender" limitToList="true" />

Acho que é isso.

[]'s

Agradeço vocês pela resposta.
Bom, concordo com vocês com relação a tudo. O que me estranha é pelo fato do meu beanGerenciado ser do tipo session e não request.
Consegui resolver meu problema da seguinte forma:

Solução tomada:
No suggestionbox, ao invés de renderizar todo o formulário, renderizei apenas os campos que devem ser modificados pelo ajax. E, ao inves e pegar o resultado apenas do código {result.codigo} peguei todo o objeto, {result}.
No campo ‘codigo’, eu retirei o ajax. A função que executava no ajax, coloquei para ser executada dentro do beanGerenciado, na função chamada pelo suggestionbox.

No mais é isso, agradeço aos amigos que disposeram a ajudar.
Caso algum de vocês tenham a documentação do a4j ou um tutorial legal a respeito dos componentes e seus atributos, seria de grande valia para crescimento profissional.

No mais, grande abraço.

Então, eu entendo o seguinte.

O que acontece é que quando você coloca o ajaxSingle=“true” e o submit ocorre, na sua requisição só será enviado o valor do próprio componente que contém o ajaxSingle. Ou seja, se você preencheu varios inputText e não os submeteu (você pode verificar isso, colocando um breakpoint nos setters, ele não será chamado) porque está com ajaxSingle=“true”. Então os valores desses inputs não serão “setados” nas suas variveis (java)

E quando ocorre a fase de renderização da sua arvore de componentes. O JSF chama os getters desses inputs, logo, estarão “vazios”, ai ele constroi o form novamente com esses valores.

Para ele não chamar esses getters você precisa deixar de forma explicita que você só quer reRenderizar os componentes que estão listados no atributo reRender, para isso, você utiliza o limitToList=“true”.

Mas se você precisa reRenderizar algum outro componente diferente do que efetuou o submite (o que contém o ajaxSingle="true), você deve informar para o JSF que ele também deve enviar o valor desse componente, para isso você pode utilizar o atributo process=“idDoComponenteQueDeveSerSubmetidoTambem”.

Dessa forma, o submite ocorre e envia os valores necessários de todos os componentes que você informou.

Tentando utilizar seu codigo como exemplo:

 <rich:suggestionbox for="descNaturezaIn" suggestionAction="#{bRLiquidacoes.autoCompletaNatureza}" var="result"   
                                     width="325" id="sugNatureza" minChars="0" nothingLabel="Sem Resultados"  
                                     fetchValue="#{result.descricao}">                                                     

                        <a4j:support id="a4j5" focus="codNaturezaIn" event="onselect" 
                             
                             limitToList="true" reRender="codNaturezaIn" 
                             ajaxSingle="true" process="codNaturezaIn"> 
                            
                             <f:setPropertyActionListener value="#{result.codigo}" target="#{bRLiquidacoes.codNat}"/>  
                     </a4j:support>                                          
 </rich:suggestionbox>



 <h:inputText id="codNaturezaIn" ......... />
 

Nesse exemplo estou querendo dizer o seguinte: Quando o usuario selecionar um item no suggestion, eu quero que seja feito um submite enviando o value do suggestion e além disso quero que seja enviado e value do inputText cujo id=“codNaturezaIn”.

E quando ocorrer a fase de renderização, eu só quero que seja renderizado o inputText

Basicamente eu sempre penso assim:

  • se tem ajaxSingle verifico se preciso adicionar um process
  • se tem reRender EU sempre utilizo limitToList.

Bom, isso é o que eu entendo. Espero que ajude.

[]'s

Já tentou usar o escopo session ?
obs: nao tinha visto que vc citou que sua scope era session
desconsidere :smiley:

Muito obrigado alex.brito! É bom ouvir opnições como a sua a respeito de como funciona as coisas.

[quote=alex.brito][quote]
que me estranha é pelo fato do meu beanGerenciado ser do tipo session e não request.
[/quote]

Então, eu entendo o seguinte.

O que acontece é que quando você coloca o ajaxSingle=“true” e o submit ocorre, na sua requisição só será enviado o valor do próprio componente que contém o ajaxSingle. Ou seja, se você preencheu varios inputText e não os submeteu (você pode verificar isso, colocando um breakpoint nos setters, ele não será chamado) porque está com ajaxSingle=“true”. Então os valores desses inputs não serão “setados” nas suas variveis (java)

E quando ocorre a fase de renderização da sua arvore de componentes. O JSF chama os getters desses inputs, logo, estarão “vazios”, ai ele constroi o form novamente com esses valores.

Para ele não chamar esses getters você precisa deixar de forma explicita que você só quer reRenderizar os componentes que estão listados no atributo reRender, para isso, você utiliza o limitToList=“true”.

Mas se você precisa reRenderizar algum outro componente diferente do que efetuou o submite (o que contém o ajaxSingle="true), você deve informar para o JSF que ele também deve enviar o valor desse componente, para isso você pode utilizar o atributo process=“idDoComponenteQueDeveSerSubmetidoTambem”.

Dessa forma, o submite ocorre e envia os valores necessários de todos os componentes que você informou.

Tentando utilizar seu codigo como exemplo:

 <rich:suggestionbox for="descNaturezaIn" suggestionAction="#{bRLiquidacoes.autoCompletaNatureza}" var="result"   
                                     width="325" id="sugNatureza" minChars="0" nothingLabel="Sem Resultados"  
                                     fetchValue="#{result.descricao}">                                                     

                        <a4j:support id="a4j5" focus="codNaturezaIn" event="onselect" 
                             
                             limitToList="true" reRender="codNaturezaIn" 
                             ajaxSingle="true" process="codNaturezaIn"> 
                            
                             <f:setPropertyActionListener value="#{result.codigo}" target="#{bRLiquidacoes.codNat}"/>  
                     </a4j:support>                                          
 </rich:suggestionbox>



 <h:inputText id="codNaturezaIn" ......... />
 

Nesse exemplo estou querendo dizer o seguinte: Quando o usuario selecionar um item no suggestion, eu quero que seja feito um submite enviando o value do suggestion e além disso quero que seja enviado e value do inputText cujo id=“codNaturezaIn”.

E quando ocorrer a fase de renderização, eu só quero que seja renderizado o inputText

Basicamente eu sempre penso assim:

  • se tem ajaxSingle verifico se preciso adicionar um process
  • se tem reRender EU sempre utilizo limitToList.

Bom, isso é o que eu entendo. Espero que ajude.

[]'s[/quote]

Informação valiosa… Com o process você pode definir quais elementos do form poderão ser utilizados através do ajax.
Valeu pela dica.