Skip to content

Tudo para WordPress, desenvolvimento web — e não só

🐛 Contact Form 7 num popup do Elementor: porque o formulário recarrega a página e como resolver

🐛 Contact Form 7 num popup do Elementor: porque o formulário recarrega a página e como resolver

Adiciona um formulário de contacto através do Contact Form 7 dentro de um popup do Elementor Pro. O utilizador preenche os campos, clica em «Enviar» e a página inteira é recarregada.

Sem mensagens de erro. Sem confirmação de envio. Apenas um recarregamento e um lead perdido.

Este é um conflito conhecido: o CF7 depende de submissão por AJAX, mas dentro de um popup carregado dinamicamente o seu JavaScript não tem tempo para se ligar ao formulário. Como resultado, o navegador executa um envio HTML padrão, precisamente aquele que causa o recarregamento.

O problema existe há anos, mas resolve-se com apenas duas linhas de código. Abaixo encontram-se duas soluções funcionais: uma moderna (mais limpa e fiável) e uma alternativa do GitHub, além de melhorias opcionais e uma lista de verificação para depuração.

💡 Resumo rápido:

  • Causa raiz: o CF7 inicializa no carregamento da página, mas o popup com o formulário aparece mais tarde, pelo que o script desconhece o seu conteúdo
  • Solução 1: reinicializar o CF7 quando o evento elementor/popup/show é disparado; o JavaScript aguarda que o popup abra e assume o formulário
  • Solução 2: monitorizar cliques no botão que abre o popup com um atraso para a animação; este método provém de uma discussão no GitHub sobre o Elementor
  • Opcional: repor o formulário ao reabrir e fechar automaticamente o popup após um envio bem-sucedido
  • Lista de verificação para depuração: consola do navegador, conflitos de jQuery, plugins de cache

Porque é que o CF7 falha especificamente num popup

Programador a corrigir um bug do Contact Form 7 no WordPress

O Contact Form 7 é construído sobre AJAX: o formulário é enviado sem recarregar, a validação dos campos acontece em tempo real e as mensagens de erro ou sucesso aparecem instantaneamente. No entanto, todo este mecanismo se liga ao DOM no carregamento da página através de uma chamada a wpcf7.init().

O Elementor Pro carrega o conteúdo do popup dinamicamente, após o evento DOMContentLoaded. Quando um utilizador clica num botão e o popup abre, o seu HTML é inserido no documento, mas o CF7 desconhece-o por completo. O formulário dentro do popup permanece não inicializado.

O que acontece a seguir: sem um manipulador AJAX ativo, o navegador executa um envio de formulário HTML padrão. O atributo action é disparado e a página recarrega. O popup fecha naturalmente (o seu estado é reposto na navegação). O utilizador vê um recarregamento e abandona a página.

Muitos programadores tentam tratar os sintomas: bloqueiam o fecho do popup com event.stopPropagation(), sobrepõem funções internas do Elementor ou impedem o envio do formulário com e.preventDefault(). Nenhum destes métodos aborda a causa raiz (a falta de inicialização do CF7). Alguns até quebram as animações do popup ou o próprio Elementor em todo o site.

Existe apenas uma solução fiável: esperar que o popup abra e chamar explicitamente wpcf7.init() para cada formulário no seu interior.

Solução 1: reinicialização ao abrir o popup (abordagem moderna)

Este método utiliza o evento nativo elementor/popup/show do Elementor. Coloque o código no functions.php do seu tema ativo ou adicione-o através de um plugin de snippets como o Code Snippets.

Crie uma cópia de segurança do functions.php antes de editar.

1/**
2 * Reinitialize Contact Form 7 when opening an Elementor popup.
3 * Fixes page reload after form submission.
4 */
5function sdstudio_cf7_reinit_in_popup() {
6 ?>
7 <script>
8 jQuery( document ).on( 'elementor/popup/show', function() {
9 document.querySelectorAll( '.wpcf7 form' ).forEach( function( form ) {
10 if ( typeof wpcf7 !== 'undefined' ) {
11 wpcf7.init( form );
12 }
13 });
14 });
15 </script>
16 <?php
17}
18add_action( 'wp_footer', 'sdstudio_cf7_reinit_in_popup' );

Depois de guardar, abra o popup com o formulário e teste-o: preencha os campos obrigatórios incorretamente e clique em «Enviar». As mensagens de validação devem aparecer instantaneamente, sem recarregamento. Em seguida, envie o formulário corretamente e confirme que a mensagem de sucesso também é exibida dentro do popup.

O código aguarda o evento elementor/popup/show, que é garantido disparar após o conteúdo do popup ter sido renderizado. Depois, querySelectorAll encontra todos os formulários CF7 no DOM atual e wpcf7.init() liga forçosamente a validação e submissão AJAX a cada um deles. A verificação typeof wpcf7 !== 'undefined' protege contra erros se, por alguma razão, o CF7 não tiver carregado.

Solução 2: monitorizar cliques no botão do popup (método alternativo)

Esta abordagem foi publicada na discussão #7798 do GitHub do Elementor pelo utilizador @drinkmaker. Em vez de monitorizar a abertura do popup, monitoriza cliques num botão ou link com href='#elementor-action', que é exatamente como o Elementor aciona os popups.

O atraso setTimeout(..., 800) concede tempo para a animação de aparecimento do popup antes de o código encontrar e inicializar o formulário. O marcador .elementor impede a reinicialização do mesmo formulário duas vezes.

1/**
2 * Alternative initialization of CF7 in Elementor popups.
3 * Source: https://github.com/elementor/elementor/issues/7798 (drinkmaker)
4 */
5function sdstudio_elementor_cf7_alt_init() {
6 ?>
7 <script type='text/javascript'>
8 jQuery( document ).ready( function() {
9
10 jQuery( document ).on( 'click', "a[href='#elementor-action']", function() {
11
12 setTimeout( function() {
13
14 jQuery( '.elementor-popup-modal form.wpcf7-form:not(.elementor)' ).each( function( index ) {
15 wpcf7.initForm( jQuery( this ) );
16 jQuery( this ).addClass( 'elementor' );
17 });
18
19 }, 800 );
20
21 });
22
23 });
24 </script>
25 <?php
26}
27add_action( 'wp_footer', 'sdstudio_elementor_cf7_alt_init' );

Qual o método a escolher: o primeiro (usando o evento elementor/popup/show) é preferível porque depende da API documentada do Elementor, é mais limpo e não depende de temporizadores. O segundo foi testado em produção durante anos e serve como um Plano B fiável se o primeiro não funcionar por algum motivo.

Opcional: repor o formulário ao reabrir

Quando um utilizador fecha o popup e o abre novamente, os campos do formulário permanecem preenchidos. Isto é confuso: não fica claro se o formulário foi ou não enviado. Uma pequena adição à primeira solução resolve isto:

1/**
2 * Reset CF7 form each time an Elementor popup opens.
3 */
4function sdstudio_cf7_reset_on_popup_open() {
5 ?>
6 <script>
7 jQuery( document ).on( 'elementor/popup/show', function() {
8 jQuery( '.wpcf7 form' ).each( function() {
9 this.reset();
10 jQuery( this ).find( '.wpcf7-not-valid' ).removeClass( 'wpcf7-not-valid' );
11 jQuery( this ).find( '.wpcf7-response-output' ).hide();
12 jQuery( this ).find( '.wpcf7-not-valid-tip' ).remove();
13 });
14 });
15 </script>
16 <?php
17}
18add_action( 'wp_footer', 'sdstudio_cf7_reset_on_popup_open' );

A função repõe os valores dos campos com reset(), remove as classes CSS dos campos inválidos, oculta as mensagens de envio e remove as dicas de validação. O utilizador vê sempre um formulário limpo.

Opcional: fechar o popup após envio bem-sucedido

Após um envio bem-sucedido, faz sentido fechar automaticamente o popup após 1,5 segundos, para que o utilizador tenha tempo de ler a confirmação sem ter de procurar o botão de fechar:

1/**
2 * Auto-close Elementor popup after successful CF7 submission.
3 */
4function sdstudio_close_popup_on_cf7_success() {
5 ?>
6 <script>
7 document.addEventListener( 'wpcf7mailsent', function() {
8 setTimeout( function() {
9 jQuery( '.dialog-close-button' ).trigger( 'click' );
10 }, 1500 );
11 }, false );
12 </script>
13 <?php
14}
15add_action( 'wp_footer', 'sdstudio_close_popup_on_cf7_success' );

O evento wpcf7mailsent é disparado quando o servidor confirma que o email foi enviado. O atraso de 1500 ms dá ao utilizador tempo para ler a mensagem de sucesso. O clique em .dialog-close-button utiliza o botão de fechar padrão do Elementor. Ao contrário das tentativas de chamar a API do popup diretamente, este método é estável em todas as versões.

Lista de verificação para depuração

Se o formulário continuar a recarregar a página após adicionar o código, siga estes passos:

  • Consola do navegador. Abra as DevTools (F12 → Consola) e verifique se há erros de JavaScript a vermelho. Uma causa comum é o jQuery não estar a carregar ou estar em conflito com outro plugin.

  • Cache. Plugins como WP Rocket, Autoptimize ou cache ao nível do servidor podem minificar e combinar scripts. Desative temporariamente a otimização agressiva de JS e teste novamente.

  • jQuery em modo noConflict. Se um tema ou plugin envolver o jQuery em noConflict, substitua jQuery por $ usando um invólucro apropriado ou utilize a forma completa jQuery.

  • ID do popup. Certifique-se de que o formulário está dentro do popup exato acionado por um botão com href='#elementor-action'. Para popups abertos através de outros tipos de acionamento (por exemplo, temporizador), o primeiro método com elementor/popup/show é mais fiável.

  • Conflito de plugins. Desative outros plugins um a um e teste, especialmente aqueles que adicionam os seus próprios scripts de validação ou modificam o comportamento dos formulários.

  • Versão do CF7. Estas soluções foram testadas no Contact Form 7 versão 5.7+ e Elementor Pro 3.5+. Se a sua versão do CF7 for inferior à 5.7, a função wpcf7.init() pode ter um nome diferente; atualize o plugin.

⁉️🤔 Perguntas frequentes

Porque é que o CF7 funciona numa página normal mas falha num popup?

Quando uma página normal carrega, o DOM já está construído e o CF7 tem tempo para inicializar todos os formulários. O popup do Elementor carrega conteúdo de forma assíncrona, depois de o CF7 ter terminado o seu trabalho. O formulário acaba no DOM, mas sem um manipulador JavaScript vinculado. É por isso que verificar «funciona numa página separada» não ajuda: as condições de carregamento são fundamentalmente diferentes. A solução é sempre a reinicialização forçada quando o popup abre, independentemente de o formulário funcionar noutro local.

Posso resolver sem código, usando um plugin ou uma configuração?

Não existe um plugin pronto que permita «marcar uma caixa e já está» para este bug. O problema situa-se na interseção de dois produtos independentes (Elementor e CF7), e cada um funciona corretamente por si só. Extensões de terceiros como o WPB Popup for Contact Form 7 resolvem o problema de forma diferente: criam os seus próprios popups em vez de corrigir o Elementor. O código acima é a intervenção mínima necessária. Adiciona-o uma vez ao functions.php e não requer atualizações quando saem novas versões do CF7 ou do Elementor.

O primeiro método não funcionou. O que devo verificar antes de mudar para o segundo?

Verifique três coisas. Primeiro: o evento elementor/popup/show está disponível a partir do Elementor Pro 2.7; se a sua versão for inferior, use o segundo método de imediato. Segundo: abra a consola e escreva typeof wpcf7; se for undefined, o plugin CF7 não carregou o seu JavaScript (procure erros ou conflitos). Terceiro: certifique-se de que o formulário dentro do popup tem a classe .wpcf7; sem ela, o seletor querySelectorAll('.wpcf7 form') não encontrará nada. Na grande maioria dos casos, o primeiro método funciona imediatamente. Se não funcionar, use o segundo: foi comprovado em centenas de sites ao longo dos anos.

Preciso de adicionar os três snippets ou basta um?

O primeiro snippet (reinicialização) é o mínimo essencial. O segundo é uma alternativa; adicione-o apenas se o primeiro não resolveu o problema. A reposição do formulário e o fecho automático do popup são melhorias opcionais que pode adicionar conforme necessário: a reposição é útil se o popup abrir várias vezes durante uma única visita; o fecho automático é útil se o popup for usado para pedidos de contacto e não contiver um texto de confirmação extenso. Todos os três snippets são independentes e podem funcionar em simultâneo. Não há conflitos entre eles.

Após a correção, o formulário envia, mas os emails não chegam. Isto está relacionado?

Não, os problemas de entrega de email são um tópico separado, não relacionado com o funcionamento do CF7 dentro de um popup. Se, após aplicar a correção, o formulário mostrar uma mensagem de sucesso (borda verde), a submissão AJAX está a funcionar corretamente. Emails que não chegam: verifique as configurações SMTP, os filtros de spam do alojamento e o endereço do destinatário nas configurações do formulário CF7. Para uma entrega fiável, use um plugin SMTP como o Post SMTP ou FluentSMTP em vez da função padrão wp_mail(), uma vez que os alojamentos bloqueiam frequentemente o envio de correio PHP.

Esta solução afeta outros formulários CF7 no site?

Não. Ambos os métodos são isolados: o primeiro aguarda que um popup do Elementor abra, o segundo monitoriza apenas links com href='#elementor-action'. Os formulários CF7 normais colocados em páginas e widgets continuam a funcionar normalmente; são inicializados no carregamento da página e permanecem inalterados. A única ressalva: se o seu site usar cache agressiva com concatenação de scripts, adicione o código do popup às exclusões de minificação para evitar a execução dupla.

Vale a pena preocupar-se com código personalizado em 2026

Ambos os plugins, Contact Form 7 e Elementor Pro, são ativamente desenvolvidos e atualizados. O CF7 mantém a sua posição como o plugin de formulários WordPress mais popular, com mais de 5 milhões de instalações ativas. O Elementor Pro é usado em cada quarto site WordPress.

No entanto, o bug aqui descrito não foi corrigido ao nível do núcleo de nenhum dos plugins e provavelmente nunca será. A razão é arquitetural: o CF7 é responsável pelos formulários, o Elementor é responsável pelo conteúdo dinâmico, e a inicialização de scripts em DOM carregado dinamicamente continua a ser da responsabilidade do programador.

A boa notícia: a correção é trivial, o código é adicionado uma vez e não requer manutenção. Escolha o primeiro método (o evento elementor/popup/show): é o mais limpo e pode esquecer o problema. Se o formulário no popup for usado para cenários críticos de geração de leads, adicione também a reposição de campos e o fecho automático: a experiência do utilizador melhorará notoriamente.

Veja o vídeo acima: mostra o processo completo de configuração de um popup com o Contact Form 7 no Elementor. Este guia visual passo a passo complementa os snippets aqui fornecidos e ajuda a evitar erros durante a montagem.