remoteFunction onchange select
27/05/2013 17:41
0
Boa tarde.

Por padrão o list exibe todo conteúdo da tabela.

Coloquei um "combobox" no meu list para que eu selecione uma categoria e em seguida ele recarregue os itens do list somente com os itens pertencentes a categoria.

Este é o select:
<g:select
id="id"
name="tipo.id"
from="${tipo.list()}"
optionKey="id"
required=""
value="${itensInstance?.categoria?.id}"
class="many-to-one"
onchange="${remoteFunction(action:'listItens', method: 'post', params:'\'categoriaId=\' + this.value' )}"
noSelection="${['null':'Selecione a categoria...']}"
/>

E em Itens listItens tenho:
def listItens() {
def categoria = Categoria.findById(params.categoriaId)
def itens = Itens.findByCategoria(categoria)
println "Categoria: "+ categoria.id
[itensInstanceList:itens, itensInstanceTotal:itens.count()]
}


O código do listItens é executado porque eu vejo no console a mensagem "Categoria: 1" por exemplo. Mas a página continua intacta, nada acontece, creio que o remoteFunction executa a função dinâmicamente mas não atualiza a view atual.

Alguém teria uma idéia de como fazer isto?

Atualizar a minha view de acordo com a seleção de uma opção no combobox?

Evaldo Wolkers.
Tags: remoteFunction, onchange, select


0
Olá Evaldo,

Esta faltando você dizer para o seu método remoteFunction o que deve ser atualizado após o retorno, é o atributo chamado 'update' que deve ser preenchido.

No exemplo da documentação, irá ser atualizado o campo 'great' caso haja sucesso e 'ohno' caso haja falha.

<select onchange="${remoteFunction(action: 'bookByName',
update: [success: 'great', failure: 'ohno'],
params: '\'bookName=\' + this.value')}">
<option>first</option>
<option>second</option>
</select>


http://grails.org/doc/2.2.1/ref/Tags/remoteFunction.html

Também existe o evento onSuccess que pode ser programado em javascript.


0
Lembrando que não será carregado a página inteira após a execução do seu método, pois o remoteFunction(...) irá gerar um código AJAX para chamar o método.


0
Clovis, obrigado, mas este exemplo da documentação eu já tinha visto, mas é muito vago para mim ainda.

O problema é que a página fica intacta, com os mesmos dados e a função do controller é executada normalmente.

Não sei como atualizar a lista que por padrão está na div "list-itens".

Alguém tem idéia de como consigo fazer isto?

Evaldo Wolkers.
27/05/2013 18:36


0
Evaldo,

Estou sem tempo para implementar um exemplo por aqui, sorry.

Mas achei esse exemplo que utiliza templates:
http://stackoverflow.com/questions/3770765/grails-load-data-on-one-combobox-depending-on-another

e esse aqui http://blog.greggbolinger.com/blog/2013/02/12/grails-g-select-with-remotefunction/ utiliza função javascript.

Espero ter ajudado.





0
Eu estou bastante cru no Grails ainda.

Vi algumas críticas neste fórum que fazem sentido.

Sobre o básico, o Grails se sai muito bem.

Encontrei bastante literatura abordando o básico do Grails.

Quando um programador começa a utilizar Grails pela primeira vez, acha muito lindo.

Mas quando esbarra em coisas como esta que estou tentando fazer (que de outra forma é bastante simples). E não consegue resolver, acaba meio que desistindo de utilizar.

Eu sei que ele é bem flexível, e o que estou tentando fazer é bem simples, mas não localizei em lugar algum um exemplo que fosse claro de como fazer isto.

Eu só quero recarregar minha view de acordo com o id de uma categoria, seria simples isso, rs.

Só que parece que não é, rs;

Evaldo Wolkers.
27/05/2013 19:32


0
Fiz assim:

HTML (Combo pai):



<label>Seleciona a Instância: </label>
<g:select name="cbInstance" noSelection="['':'']" from="${instances}" optionValue="name" optionKey="id" onchange="${remoteFunction(action: 'getLabs', onSuccess: 'updateLabs(data)', params:'\'id=\' + escape(this.value)')}; \$('#cbLabs').focus()"></g:select>



HTML (Combo filho):



<label>Selecione o Laboratório: </label>
<g:select name="cbLabs" from="" noSelection="['':'']" onchange="\$('#schCode').focus()" style="width: 100px"></g:select>



Javascript:


function updateLabs(data) {
$("#cbLabs").empty()
$("#cbLabs").append(new Option("", ""))
for (i=0; i < data.length; i++) {
$("#cbLabs").append(new Option(data[i].labcode, data[i].id))
}
}

27/05/2013 20:08


0
Luiz,

No seu exemplo, você está alterando o conteúdo de um combobox que você criou (cbLabs), no meu caso, tenho que alterar o conteúdo do InstanceList padrão, já que estou usando scaffold padrão.

Isso que não estou conseguindo fazer.

Evaldo Wolkers.
27/05/2013 20:31


0

O código do listItens é executado porque eu vejo no console a mensagem "Categoria: 1" por exemplo. Mas a página continua intacta, nada acontece, creio que o remoteFunction executa a função dinâmicamente mas não atualiza a view atual.


Evaldo, o que você quer dizer com "não atualiza a view atual"? Qual comportamento que você espera? Talvez eu não tenha entendido bem o que você deseja.

Um remoteFunction deve ser utilizado para atualizar um pedaço do seu HTML ou executar um javascript no retorno da chamada.

No meu caso, por exemplo, eu uso para chamar um Javascript. Mas você poderia utilizar para atualizar uma tag div html. Nesse caso, sua action deveria retornar um HTML que será substituído pelo HTML atual no retorno da chamda do remoteFunction.

No seu remoteFunction não existe update ou onSuccess, você está simplesmente fazendo uma chamada pra sua action e não tá fazendo nada com o retorno.
27/05/2013 21:06


0
Olá Luiz, deixa eu tentar explicar.

Criei um crud padrão (scaffold).

O Grails criou o show, create, edit e list para o meu controller.

No list (gsp) padrão o Grails cria um objeto ObjetoInstanceList e faz um loop alimentando uma tabela.

Estou nesta tela, com a listagem dos meus itens.

Aí acrescentei no list.gsp uma combobox com as categorias, queria que ao selecionar uma categoria, minha list exibisse todos itens daquela categoria.

Mas isso não está acontecendo.

Evaldo Wolkers.
27/05/2013 22:35


0
Evaldo,

Agora entendi o seu problema.

O comportamento que você deseja não está acontecendo, pois não está programado pra isso.

Basicamente, você tem quatro opções para atualizar a sua table HTML baseado na seleção do combobox:

1. Mais simples: no onchange do seu combobox você executa o javascript: window.location.href=${createLink(action: 'suaaction')} + '&idCategoria=' + idSelecionadoComboBox (pode ser obtido via jquery). Problema com essa abordagem: um refresh será dado na tela, já que ela não é AJAX.

2. Fazer sua action retornar uma table HTML completa. Assim, por meio do update do remotefuncion você atualiza a div onde está a tabela atual. O remoteFunction vai substituir um HTML pelo outro.

3. Fazer sua action retornar um JSON e criar uma função javascript que percorre esse JSON e atualiza sua tabela.

4. Montar um template GSP (templates começam com _). O único trabalho desse template é renderizar a sua tabela HTML recebendo como modelo da sua action as variáveis necessárias. Nesse caso, a sua action tem que finalizar dando um render para esse template: render(template: "tabelaItens.gsp", model: [itens:Itens.list()]). No seu list.gsp você retira todo o código que renderiza a tabela e troca por <g:render template="tabelaItens" />

Gosto mais da 4a opção, pois é simples e AJAX.

Escrevi rapido, então deve ter coisa incoerente, mas tente trilhar um desses caminhos que você conseguirá o que precisa.

Sobre Grails: é tão fácil que tudo parece mágica, mas não é. Fique ligado. :-)


28/05/2013 00:02


0
Luiz.

Obrigado.

Desisti do combo na página "list".

Criei uma página separada para seleção das categorias antes de entrar na página de itens.

Evaldo Wolkers.
28/05/2013 05:11


0
Blza Evaldo, mas não deixe de olhar os templates. São muito úteis e são fáceis de utilizar. A princípio parecem complicados, mas não são.

Penso que muito da sua dificuldade está no fato de você estar construindo sua app baseado no scaffold gerado pelo Grails. Minha opinião sobre scaffold é que eles são muito úteis pra aprender, mas devem parar por aí. Não são maduros (e nem sei se devem ficar) para construção de aplicações reais.

Estamos fazendo um sistema e usando de maneira intesa o plugin jqGrid para tabelas de dados. Por se tratar de um sistema corporativo (sistema comercial) é normal que hajam muitos cadastros, muitas tabelas. Se for este o seu caso, não deixe de dar uma olhada: http://trirand.com/blog/jqgrid/jqgrid.html



28/05/2013 12:47


0
O scaffold deve ser utilizado, principalmente, para geração rápida de telas de admin.

Evaldo, pelo que compreendi do seu problema, ele não estava atualizando a div apenas, talvez seja algum erro na codificação do retorno da chamada, pois vc tem resposta.

Uma outra forma seria implementar sua chamada AJAX com $.ajax{} (JQuery) e implementar o código na unha mas lembre-se Don't Repeat Yourself (DRY).

O Luiz comentou sobre os templates, eu os recomendo fortemente para requisições AJAX, já que está é a principal função pela qual eles foram concebidos dentro do framework (não disse que é a única, lembre-se disso). Basta inserir um _nomeTemplate no nome do gsp e voilà!

Enfim. Existem outras formas de fazer isso, e não vou me estender. Mas não desanime!

Abs e boa sorte com o projeto!


0
Obrigado pelas dicas Eduardo.

Consegui fazer o que queria.

Abraços,

Evaldo Wolkers.
03/06/2013 19:52



Ainda não faz parte da comunidade???

Para se registrar, clique aqui.


Aprenda Groovy e Grails com a Formação itexto!

Newsletter Semana Groovy

Assinar

Envie seu link!


Livro de Grails


/dev/All

Os melhores blogs de TI (e em português) em um único lugar!

 
Creative Commons
RSS Grails Brasil é mantido por itexto Consultoria.
Em caso de problemas contacte Henrique Lobo Weissmann (Kico) por e-mail: kico@itexto.com.br
Todo o conteúdo presente neste site adota o Creative Commons como licença padrão.
Ver: 4.14.0
itexto