Evento submit e método submit() em JavaScript
Aprenda como o evento submit, form.submit() e form.requestSubmit() funcionam em JavaScript: validação, preventDefault(), o botão submitter e leitura de dados do formulário antes do envio.
O tratamento de envios de formulários é uma das tarefas mais comuns no front-end com JavaScript. Os formulários são a forma como os usuários enviam dados de volta ao servidor — fazendo login, registrando-se, pesquisando, finalizando compras — portanto, você quase sempre quer ter a chance de validar, transformar ou confirmar esses dados antes que saiam da página.
Existem duas ferramentas relacionadas, mas distintas, para isso:
- O evento
submit— disparado pelo navegador quando o usuário tenta enviar um formulário (clicando em um botão de envio ou pressionando Enter em um campo). É aqui que você executa a validação e decide se permite ou cancela o envio. - O método
form.submit()— envia o formulário programaticamente a partir do seu código, sem nenhuma ação do usuário.
Um detalhe importante que confunde muitos desenvolvedores: os dois não são simétricos. Chamar form.submit() não dispara o evento submit e ignora completamente a validação de restrições. Vamos explicar o porquê e o que usar no lugar.
Entendendo o evento submit
O evento submit é disparado quando um formulário está prestes a enviar seus dados. É fundamental que ele seja cancelável: chamar event.preventDefault() dentro do manipulador impede que o navegador navegue para outra página, permitindo que o usuário permaneça na página para validar a entrada, exibir erros ou enviar os dados com fetch em vez disso.
O evento é disparado quando:
- O usuário clica em um
<button type="submit">ou<input type="submit">dentro do formulário. - O usuário pressiona Enter enquanto está focado em um campo de texto de um formulário que possui um botão de envio.
Ele não é disparado quando você chama form.submit() a partir de JavaScript (veja abaixo).
Exemplo: Validação de formulário antes do envio
Este script impede que o formulário seja enviado se os campos não estiverem preenchidos corretamente, exibindo uma mensagem de erro ao usuário. Ele usa a validação de restrições nativa do navegador (o atributo required e type="email") por meio de checkValidity().
<div>
<form style="display: flex; justify-content: center; gap: 2px; align-items: center; flex-direction: column;" id="registrationForm">
Username: <input type="text" name="username" required />
Email: <input type="email" name="email" required />
<button type="submit">Register</button>
</form>
<div id="message" style="margin-top: 10px; text-align:center;"></div> <!-- Message container for feedback -->
<script>
const form = document.getElementById('registrationForm');
form.addEventListener('submit', function(event) {
event.preventDefault(); // Prevent actual form submission to a server
const messageDiv = document.getElementById('message');
if (!this.checkValidity()) {
messageDiv.textContent = 'Please fill all required fields correctly.';
messageDiv.style.color = 'red'; // Display the message in red for errors
} else {
messageDiv.textContent = 'The form was successfully submitted.';
messageDiv.style.color = 'green'; // Display the message in green for success
form.reset(); // Reset the form fields after successful submission
}
});
</script>
</div>Funcionalidade JavaScript:
- Listener de evento: Um listener de evento é anexado ao formulário e é acionado quando o envio do formulário é tentado.
- Verificação de validação: A função
checkValidity()é usada aqui. É um método nativo de formulário HTML que verifica todas as entradas do formulário em relação às suas regras de validação (como o atributorequiredneste caso). Se algum campo não atender à sua regra de validação, a função retorna false. - Impedir envio: Se
checkValidity()retornar false (o que significa que o formulário possui campos obrigatórios inválidos ou vazios), o script impede que o formulário seja enviado ao servidor. Em vez disso, exibe uma mensagem pedindo ao usuário que preencha todos os campos obrigatórios corretamente. - Tratamento do envio: Se todos os campos forem válidos, o formulário exibe uma mensagem de sucesso em vez de mostrar uma página em branco ou enviar para um servidor. Em um aplicativo real, é aqui que você chamaria
fetch()para enviar os dados.
Lendo os dados enviados
Dentro do manipulador, você geralmente quer os valores digitados pelo usuário. A maneira mais limpa é usar o objeto FormData, que coleta todos os controles nomeados em um único passo:
const form = document.getElementById("registrationForm");
form.addEventListener("submit", (event) => {
event.preventDefault();
const data = Object.fromEntries(new FormData(form));
console.log(data.username, data.email);
// data is a plain object: { username: "...", email: "..." }
});Sabendo qual botão foi clicado
Quando um formulário tem vários botões de envio (por exemplo, "Salvar" vs. "Excluir"), o evento submit informa qual deles o acionou por meio de event.submitter:
form.addEventListener("submit", (event) => {
event.preventDefault();
// event.submitter is the button element that caused submission
console.log("Submitted via:", event.submitter?.value);
});Usando o método .submit()
O método .submit() inicia o envio do formulário de forma programática — diretamente do seu código, sem que nenhum clique do usuário seja necessário. É útil quando um formulário deve ser enviado após alguma condição ser atendida (um temporizador, uma verificação automatizada aprovada, um valor calculado em JavaScript).
Dois pontos importantes fazem com que .submit() se comporte de forma diferente de um envio feito pelo usuário:
- Ele não dispara o evento
submit, portanto, qualquer validação ou lógica que você tenha associado a esse evento é ignorada. - Ele não executa a validação de restrições do navegador, portanto, as regras de
requiredetypesão ignoradas.
Isso é intencional — historicamente, .submit() foi projetado para enviar sem executar novamente o próprio manipulador que o chamou (o que, de outra forma, causaria um loop). Na maioria dos casos, você deve preferir form.requestSubmit() (abordado abaixo), que se comporta como um envio real feito pelo usuário.
Exemplo: Envio programático de formulário
O exemplo abaixo envia um formulário a partir do código assim que a página é carregada. Como o formulário não possui atributo action, ele envia de volta para a página atual; o alerta mostra o valor do campo oculto para que você possa ver o que seria enviado:
<!DOCTYPE html>
<html>
<head>
<title>Auto Submit Form Demo</title>
</head>
<body>
<form id="autoSubmitForm">
<input type="hidden" name="data" value="Automatic Submission" />
</form>
<script>
function submitFormAutomatically() {
document.getElementById('autoSubmitForm').submit();
alert("Form submitted with data: " + document.getElementById('autoSubmitForm').data.value);
}
document.addEventListener('DOMContentLoaded', submitFormAutomatically); // Call the function when the DOM is ready
</script>
</body>
</html>Observe que document.getElementById('autoSubmitForm').data funciona porque os controles de formulário nomeados são expostos como propriedades no elemento do formulário — form.data retorna o elemento <input name="data">, e .value lê seu valor.
Prefira requestSubmit() em vez de submit()
form.requestSubmit() é a alternativa moderna e mais segura para form.submit(). Ao contrário de .submit(), ele:
- dispara o evento
submit, para que seus manipuladores de validação sejam executados; - executa a validação de restrições do navegador e exibe balões de erro nativos se um campo for inválido;
- opcionalmente aceita um botão para que
event.submitterseja definido, por exemploform.requestSubmit(saveButton).
const form = document.getElementById("registrationForm");
// Behaves exactly like a real user click on the submit button:
form.requestSubmit();Se você realmente precisar do comportamento de desvio do .submit(), mas ainda quiser que seu manipulador seja executado, você pode despachar o evento você mesmo com form.dispatchEvent(new Event('submit', { cancelable: true })) — mas, em quase todos os casos, requestSubmit() é a chamada certa.
Combinando .submit() com listeners de evento
Você também pode condicionar o envio a critérios próprios: só envia o formulário quando determinadas condições são atendidas. O exemplo abaixo usa um botão simples (sem tipo submit) para que nada aconteça até que o JavaScript decida chamar submit().
Exemplo: Envio condicional de formulário
<form id="conditionalForm">
Accept Terms: <input type="checkbox" id="acceptTerms">
<button type="button" onclick="checkAndSubmit()">Submit</button>
</form>
<script>
function checkAndSubmit() {
var form = document.getElementById('conditionalForm');
var termsCheckbox = document.getElementById('acceptTerms');
if (termsCheckbox.checked) {
form.submit();
} else {
alert('You must accept the terms and conditions to proceed.');
}
}
</script>Este código fornece um botão que, ao ser clicado, verifica se uma caixa de seleção está marcada antes de enviar o formulário. Se os termos não forem aceitos, o usuário recebe um alerta. Observe que, como form.submit() é usado aqui, o evento submit não será disparado — substitua por form.requestSubmit() se você também tiver um listener submit que deseja executar.
evento submit vs. submit() vs. requestSubmit()
| Comportamento | evento submit | form.submit() | form.requestSubmit() |
|---|---|---|---|
| Acionado por ação do usuário | Sim | Não (somente código) | Não (somente código) |
Dispara o evento submit | — | Não | Sim |
| Executa validação de restrições | n/d | Não | Sim |
Pode ser cancelado (preventDefault) | Sim | Não | Sim (via evento) |
Define event.submitter | Sim | Não | Sim (passe um botão) |
Regra geral: ouça o evento submit para validar e interceptar; chame requestSubmit() para acionar um envio a partir do código; recorra a .submit() somente quando precisar especificamente ignorar seus próprios manipuladores.
Conclusão
O evento submit permite interceptar e validar um formulário antes que ele saia da página, enquanto .submit() e requestSubmit() permitem enviá-lo a partir do código. O ponto mais importante é que .submit() silenciosamente ignora tanto o evento submit quanto a validação — portanto, prefira requestSubmit(), a menos que você deliberadamente queira esse desvio. Combinados com event.preventDefault() e FormData, essas ferramentas oferecem controle total sobre como a entrada do usuário é coletada e enviada.
Para ir além, consulte propriedades e métodos de formulários, a API de validação de restrições, os eventos change e input para reações em tempo real nos campos, e focus e blur para interação no nível do campo.