Categorias

Arquivos

Por que meus eventos param de funcionar depois de uma requisição Ajax

Postado em Novembro 22nd, 2007 por Alexandre Magno

Ajax, Jquery

Os dois primeiros parágrafos foram traduzidos de Why do my events stop working after an Ajax request? E o restante do texto uma abordagem sobre o tema

Frequentemente, quando você adiciona um evento click (ou qualquer outro) para todos os links usando $('a').click(fn), você encontrará que os eventos não funciona mais depois que você carrega um novo conteúdo para a página usando uma requisição Ajax.

Quando você chama $('a') ele retorna todos os links na página no momento e .click(fun) adiciona o handler para cada individual elemento. Quando novos links são adicionados, eles não são afetados pelos manipuladores de eventos(que seria o handler).

O que acontece é um problema da própria requisição httprequest, não de alguma framework, poderia culpar até o javascript, mas ele nunca pensou que fosse ficar tão famoso :-) com o Ajax, que nunca sonhou em ser uma ferramenta tão utilizada e cogitada.

Existe uma solução para jQuery chamada Livequery que permite que os eventos sejam reativados depois da página ser carregada com um novo dom, mas ela faz isto de maneira automática, carregando eventos e dependendo da dimensão do projeto, realmente deixa a memória do lado cliente sobrecarregada.

Existe um método chamado event delegation que permite anexar eventos somente necessários para o funcionamento dos novos eventos no dom carregado.

Este método é essencial para quem trabalha em um projeto Ajax maior.

Este é um post de compartilhamento sobre o assunto, e estejam abertos a comentar.

 


Comentários

Assine o RSS para comentários

Diego Carrion comentou:

23rd Novembro, 2007 às 8:46 am

Alexandre, e o jQuery quem deveria ser culpado, não o JavaScript.

Eu utilizo bastante o Dojo e com ele não acontecem esses problemas.

admin comentou:

25th Novembro, 2007 às 2:50 pm

Bem, andei pesquisando várias frameworks e o próprio artigo deste post falam sobre o uso de event delegation em um projeto de navegação em ajax e a única framework que possui este uso no próprio core da framework é o Yahoo UI. Você já tentou carregar uma página em ajax e com um link dentro dela que também atualiza um dom via httprequest? Não sei como o DOJO funciona e se puder compartilhar com a gente como ele trabalha com o Ajax seria ótimo… abraços e sucesso…

Daniel Ribeiro comentou:

30th Novembro, 2007 às 10:57 am

Olá alexandre, estou iniciando em jquery agora, mas já estou terminando um sistema com js todo jquery, e estou com um problema no plugin clipregion http://amountaintop.com/sandbox/clipregion/,
o único que funcionou para o que eu queriae consegui adaptar, mas estou com uma problema de instancia, preciso que funcione em mais de um lugar na pagina independente, e não sei fazer essa alteração sem estragar o plugin, se puder dar uma dica agradeceria muito….

Agradeço desde já a atenção!

Joao comentou:

10th Dezembro, 2007 às 10:10 pm

Ajax é uma tecnologia relativamente nova e deve demorar um pouco mais para que tudo funcione corretamente para todos.

Alexsandro comentou:

23rd Junho, 2008 às 2:49 pm

é problema do httprequest e do JS e do browser sim.. o cado do DOJO pode ser que eles cuidaram deste problema no proprio core do DOJO. nada mais que isto…

mas uma vez, isto é tanto problema do browser com o JS e httprequest pois como sabemos a cada Ajax o body do HTML é modificado e quand o gente pedisse pra ver o source code dever aparecer o atual atual e não o primeiro source.

não diria que isto seja um bug, eu diria que isto é nada mais que o fluxo normal.

Maujor comentou:

18th Março, 2009 às 7:43 pm

A funcionalidade de adicionar eventos a elementos futuros do DOM proporcionada pelo plugin Livequery - citado na matéria pelo Alexandre - foi adicionada no core da biblioteca a partir da sua versão 1.3 com a criação de uma método que foi denominado live().
Um exemplo da sintaxe para este método é mostrado a seguir:
$('a').live('click', function(){...})
Agora o evento clique será adicionado tanto aos links da página que faz a requisição como aos do conteúdo requisitado.

Alexandre Magno comentou:

18th Março, 2009 às 8:09 pm

@Maujor: Bem lembrado Maujor. É uma grande funcionalidade que agora está no core do jQuery. Ela deve ser utilizada com cuidado, pois se usado da forma indevida pode anexar muitos eventos em um só elemento e gerar resultados não previstos. É sempre uma boa prática utilizar o “unbind” quando for anexar um novo evento em um elemento que tenha já um evento ligado a ele.

Chris Benseler comentou:

18th Julho, 2009 às 6:57 pm

O Maujor falou do plugin que exsitia para a jQuery e que agora virou core: tive uns problemas graves de memória com o plugin em dois projetos - o mesmo parece que ficava maluco quando a quantidade de “listeners” crescia muito - então resolvi não usar (nem agora que está no core) e prefiro ter funções específicas que atualizam os listeners após uma requisicão assíncrona.
De qualquer forma, quem disse que a culpa é da jQuery, falou bobeira, pois essa é uma condição do próprio javascript mesmo, como você afirmou.

[]s

Fernando Filho comentou:

30th Julho, 2009 às 11:15 am

Bom, eu já uso o livequery nas minhas aplicações mas o problema é que ele funciona como um bind e precisa de um evento. Como posso fazer para declarar um plugin que funcione no site todo, inclusive dentro de requests AJAX?

Alexandre Magno comentou:

30th Julho, 2009 às 3:36 pm

@Fernando: Somente por estas informações não sei o que você precisa fazer realmente. O que o plugin faz? Se ele tiver evento interno, deve usar o live ou o controle de eventos manualmente. Abraços…

Fernando Filho comentou:

30th Julho, 2009 às 4:20 pm

Imagina o datepicker do jqueryUI declarado uma única vez no head da página - $(”#date”).datepicker(); - este exemplo não funciona após o retorno do Ajax. O que devo fazer?

Alexandre Magno comentou:

30th Julho, 2009 às 6:05 pm

@Fernando: O datepicker é atribuído a um evento, ele aparece no focus, por isto não funciona. Você deve chamá-lo somente na página que irá usar e após a requisção ter sido feita. Não conheço o projeto como um todo, mas o fato é que você tem que planejar melhora arquitetura para poder ter os eventos funcionando corretamente e sob demanda no caso de muitas requisições ajax.
Abraços e boa sorte…

Fernando Filho comentou:

31st Julho, 2009 às 8:14 am

Ai que eu queria chegar, gostaria de saber mais sobre metodologias de desenvolvimento ajax e arquiteturas ajax. O que posso fazer, o que posso ler? Está me parecendo que o uso de plugins jquery em um sistema é uma furada….

Alexandre Magno comentou:

31st Julho, 2009 às 9:53 am

@Fernando: Não é uma furada usar plugins para jQuery em aplicações ajax. Na verdade eles são essenciais para ter reutilização de código, componentes. A única coisa necessária são boas práticas, planejamento e entendimento do contexto geral. É muito fácil que o javascript acabe ficando complexo e incontrolável com o crescimento das aplicações. Várias abordagens sobre este assunto e técnicas como o lowpro (http://www.learningjquery.com/2008/05/using-low-pro-for-jquery) são utilizadas, além de design patterns para javascript. Neste caso depende do desenvolvedor em utilizar ou não. Irei publicar mais posts sobre arquitetura de aplicações ajax e boas práticas.
Espero ter ajudado e boa sorte…

Fernando Filho comentou:

31st Julho, 2009 às 4:20 pm

Estou aguardadado novos posts. O lowpro me pareceu bem interessante. É exatamente isso que eu preciso uma metodologia nova, tenho habilidade para criar plugins jquery, e em usar, mas é a primeira vez que me deparo com um sistema web e vi que minhas metodologias não são ideais para o tal. Abs, obrigado pela luz!

Alexandre Magno comentou:

31st Julho, 2009 às 5:09 pm

@Fernando: Que ótimo fernando! Boa sorte cara, realmente isto é um desafio não só para você, mas para todos. Vou publicar alguns posts a respeito por que é dúvida de muita gente.
Um grande abraço…

José Morettoni comentou:

21st Outubro, 2009 às 6:53 pm

Alexandre, parabéns pelos post e pela disponibilidade.
Estou desenvolvendo um aplicativo em php e jquery para simular uma tabela de ranking dinâmico cuja qual cada par linha coluna passa o value para o bd (a coluna passa o id da etapa e a linha passa o id atleta .)

No modo convencional(atualizando a pagina a cada requisicao) tudo funciona de boa. O problema esta na remontagem da tabela apos o evento load do jquey, quando a tabela atualiza com as novas posicoes do ranking.

Pelo seu artigo li que preciso usar a livequery ou e evento incorporado $live citado pelo maujor. A ainda a opção de seu outro post , o event $delegate.
Já estou me apronfundando nele aqui, espero que consiga resolver o problema de perder os eventos depois do load.

Contudo tenho uma outra dúvida que talvez você possa me ajudar.
Na montagem da tabela dinâmica , cada linha e coluna recebe o id do atleta e o id da etapa pelo php, para que no momento da atualização possamos saber o valor antigo que o atleta obtinha e substitui-lo no bd, bem como subtrair do total de pontos do atleta o valor antigo e somar o valor novo para ter a nova pontuação..
Quando eu associo o evento $ load ou $post para enviar os dados ao php, ele só funciona para o primeiro form da linha ou coluna, devido ao id repetido, ja até tentei usar a instancia da classe, mas não tive sucesso.
Só funcionou para os outros quando eu gero as funcoes do script js direto do php e depois ‘assign’ ela no tpl, gerando um id concatenado para cada linha e coluna, mas isso nao me parece uma boa prática.

Será que depois deste testamento você pode me dar alguma indicação de como resolver isso e ter um código mais limpo e separado?

Agradecimentos e novamente parabéns pelo trabalho desenvolvido.

Alexandre Magno comentou:

25th Outubro, 2009 às 6:47 pm

@Jose: Olá, da forma que explicou ficou bastante confusa, tente dividir o problema em partes. Apesar de não ter entendido a fundo, sei que o que está fazendo não é uma boa prática. Para atualizar uma tabela maninpulando dados da forma que você está descrevendo existe muitas formas de fazer. Uma dela e fazer requisicao obtendo os valores da tabela atraves de seletores jQuery e envie um post com esses dados obtidos. No PHP quando recebe ele processa mas a resposta sera um xml ou json ou ate mesmo html para ser manipulado. Você tem a opção de retormar a coluna afetada, lembrando que se tiver qualquer evento associado a ele antes da requisição não irá funcionar se os eventos não forem feitos por live.
Espero ter ajudado. Abraços…

Lucas comentou:

5th Fevereiro, 2010 às 11:41 am

Esse Post me ajudou bastante, fiz um aplicativo aqui de envio de newsletter todo baseado em ajax e estava tendo esse problema de preservar os eventos em algumas partes.

a solução citada pelo Maujor caiu como uma luva.

Ótimo post. Parabéns

Rafael comentou:

10th Julho, 2010 às 5:33 pm

Nossa, tava sofrendo a dias com um problema aqui, de carregar uma página via ajax, e assim que for abrir o link dentro da página carregada, o AJAX não funcionar…

Baixei o livequery aqui, mais não soube utilizar, o comentário do Maujor me ajudou muito, coloquei o .live e funciona perfeitamente agora…

Agradeço ao Alexandre Magno pelo Post que ajudou, e pelo Maujor pelo comentário postado!

Deixe seu comentário

Os seguintes campos estão incorretos ou faltando

  • Listagem dos campos faltando
(Não será publicado) * Campos obrigatórios