Atualização do post – 28/03/2018
Atualmente há melhor formas de lidar com requisições ajax. Temos um ótimo post sobre Promises no Tableless.
De qualquer forma, este post é útil para você entender como uma requisição Ajax afeta eventos no DOM.

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.

23 Replies to “Por que meus eventos param de funcionar depois de uma requisição Ajax”

  1. 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…

  2. 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!

  3. é 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.

  4. 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.

  5. @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.

  6. 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

  7. 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?

  8. @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…

  9. @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…

  10. 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….

  11. @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…

  12. 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!

  13. @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…

  14. 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.

  15. @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…

  16. 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

  17. 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!

  18. Cara, parabéns!!!!Tava quebrando a cabeça e não achava a solução, foi só refazer o script sem o JQuery que o as requisições AJAX voltarma a funcionar…

  19. Cara, estou com o seguinte problema. Vários plugins jquery sendo carregados normalmente através do uso da tag “” quando a pagina é carregada. Apos a requisição AJAX eles param de funcionar. Como seria a melhor forma para recarregar esses arquivos .js novamente para que os plugins voltem a funcionar?! OO

    1. @Thiago: como está explicado no post, você deve ter funções ou classes que anexam eventos depois que a requisição ajax foi feita, ou usar o delegate que está disponível em novas versões do jQuery, dê uma olhada a respeito, pois depende muito de cada caso. Espero ter ajudado e boa sorte.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *