W3docs

Evento submit() y métodos de formularios en JavaScript

Aprende cómo funcionan el evento submit, form.submit() y form.requestSubmit() en JavaScript: validación, preventDefault(), el botón submitter y cómo leer los datos del formulario antes de enviarlos.

Manejar el envío de formularios es una de las tareas más comunes en el JavaScript de front-end. Los formularios son la manera en que los usuarios envían datos a un servidor — iniciar sesión, registrarse, buscar, realizar compras — por lo que casi siempre querrás tener la oportunidad de validar, transformar o confirmar esos datos antes de que abandonen la página.

Existen dos herramientas relacionadas pero distintas para esto:

  • El evento submit — disparado por el navegador cuando el usuario intenta enviar un formulario (haciendo clic en un botón de envío o pulsando Enter en un campo). Aquí es donde ejecutas la validación y decides si permitir o cancelar el envío.
  • El método form.submit() — envía el formulario programáticamente desde tu código, sin ninguna acción del usuario.

Un error clave que confunde a muchos desarrolladores: estos dos no son simétricos. Llamar a form.submit() no dispara el evento submit y omite por completo la validación de restricciones. Veremos por qué, y qué usar en su lugar.

Entendiendo el evento submit

El evento submit se dispara cuando un formulario está a punto de enviar sus datos. De forma crucial, es cancelable: llamar a event.preventDefault() dentro del manejador detiene al navegador para que no navegue fuera de la página, lo que te permite mantener al usuario en la página para validar la entrada, mostrar errores o enviar los datos con fetch en su lugar.

El evento se dispara cuando:

  • El usuario hace clic en un <button type="submit"> o <input type="submit"> dentro del formulario.
  • El usuario pulsa Enter mientras tiene el foco en un campo de texto de un formulario que tiene un botón de envío.

No se dispara cuando llamas a form.submit() desde JavaScript (ver más abajo).

Ejemplo: Validación del formulario antes del envío

Este script impide que el formulario se envíe si los campos no están rellenados correctamente, proporcionando un mensaje de error al usuario. Se basa en la validación de restricciones integrada del navegador (el atributo required y type="email") a través 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>

Funcionalidad de JavaScript:

  • Escuchador de eventos: Se adjunta un escuchador de eventos al formulario que se activa cuando se intenta enviar el formulario.
  • Verificación de validación: Aquí se utiliza la función checkValidity(). Es un método de formulario HTML integrado que verifica todos los campos del formulario según sus reglas de validación (como el atributo required en este caso). Si algún campo no cumple su regla de validación, la función devuelve false.
  • Prevenir el envío: Si checkValidity() devuelve false (lo que significa que el formulario tiene campos requeridos inválidos o vacíos), el script impide que el formulario se envíe al servidor. En su lugar, muestra un mensaje pidiendo al usuario que rellene todos los campos requeridos correctamente.
  • Gestión del envío: Si todos los campos son válidos, el formulario muestra un mensaje de éxito en lugar de mostrar una página en blanco o enviar al servidor. En una aplicación real, aquí es donde llamarías a fetch() para enviar los datos.

Leer los datos enviados

Dentro del manejador normalmente querrás los valores que escribió el usuario. La manera más limpia es el objeto FormData, que recopila todos los controles con nombre en un solo paso:

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: "..." }
});

Saber qué botón se pulsó

Cuando un formulario tiene varios botones de envío (por ejemplo "Guardar" vs. "Eliminar"), el evento submit te indica cuál lo activó a través 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 el método .submit()

El método .submit() inicia el envío del formulario de forma programática — directamente desde tu código, sin necesidad de que el usuario haga clic. Es útil cuando un formulario debe enviarse después de que se cumpla alguna condición (un temporizador, una comprobación automática superada, un valor calculado en JavaScript).

Dos advertencias hacen que .submit() se comporte de manera diferente a un envío iniciado por el usuario:

  • No dispara el evento submit, por lo que cualquier validación o lógica que hayas asociado a ese evento se omite.
  • No ejecuta la validación de restricciones del navegador, por lo que las reglas required y type se ignoran.

Esto es por diseño — históricamente .submit() fue pensado para enviar sin volver a ejecutar el mismo manejador que lo llamó (lo que de otro modo crearía un bucle). En la mayoría de los casos deberías preferir form.requestSubmit() (descrito a continuación), que se comporta como un envío real del usuario.

Ejemplo: Envío programático del formulario

El ejemplo siguiente envía un formulario desde el código tan pronto como se carga la página. Como el formulario no tiene atributo action, hace un post a la página actual; la alerta muestra el valor del campo oculto para que puedas ver lo que se enviaría:

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

Observa que document.getElementById('autoSubmitForm').data funciona porque los controles de formulario con nombre están expuestos como propiedades en el elemento del formulario — form.data devuelve el elemento <input name="data">, y .value lee su valor.

Prefiere requestSubmit() sobre submit()

form.requestSubmit() es el equivalente moderno y más seguro de form.submit(). A diferencia de .submit():

  • dispara el evento submit, por lo que se ejecutan tus manejadores de validación;
  • ejecuta la validación de restricciones del navegador y muestra burbujas de error nativas si un campo es inválido;
  • opcionalmente acepta un botón para que se establezca event.submitter, p. ej. form.requestSubmit(saveButton).
const form = document.getElementById("registrationForm");
// Behaves exactly like a real user click on the submit button:
form.requestSubmit();

Si realmente necesitas el comportamiento de omisión de .submit() pero aun así quieres que se ejecute tu manejador, puedes despachar el evento tú mismo con form.dispatchEvent(new Event('submit', { cancelable: true })) — pero en casi todos los casos requestSubmit() es la opción correcta.

Combinando .submit() con escuchadores de eventos

También puedes condicionar el envío a tus propias condiciones: solo enviar el formulario cuando se cumplan ciertos criterios. El ejemplo siguiente usa un botón simple (no de tipo submit) para que no ocurra nada hasta que JavaScript decida llamar a submit().

Ejemplo: Envío condicional del formulario

<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 proporciona un botón que, al hacer clic, verifica si una casilla de verificación está marcada antes de enviar el formulario. Si no se aceptan los términos, alerta al usuario. Ten en cuenta que como aquí se usa form.submit(), el evento submit no se disparará — cámbialo por form.requestSubmit() si también tienes un escuchador de submit que quieres que se ejecute.

submit event vs. submit() vs. requestSubmit()

ComportamientoEvento submitform.submit()form.requestSubmit()
Activado por acción del usuarioNo (solo código)No (solo código)
Dispara el evento submitNo
Ejecuta la validación de restriccionesn/aNo
Puede cancelarse (preventDefault)NoSí (a través del evento)
Establece event.submitterNoSí (pasa un botón)

Regla general: escucha el evento submit para validar e interceptar; llama a requestSubmit() para activar un envío desde el código; recurre a .submit() solo cuando específicamente necesites omitir tus propios manejadores.

Conclusión

El evento submit te permite interceptar y validar un formulario antes de que abandone la página, mientras que .submit() y requestSubmit() te permiten enviarlo desde el código. La conclusión más importante es que .submit() omite silenciosamente tanto el evento submit como la validación — por lo que debes preferir requestSubmit() a menos que deliberadamente quieras ese comportamiento de omisión. Combinados con event.preventDefault() y FormData, estas herramientas te dan control total sobre cómo se recopila y se envía la entrada del usuario.

Para profundizar más, consulta propiedades y métodos de formularios, la API de validación de restricciones, los eventos change e input para reacciones en tiempo real a los campos, y focus y blur para la interacción a nivel de campo.

Práctica

Práctica
¿Cuáles de las siguientes afirmaciones son verdaderas sobre el evento submit y el método submit() de JavaScript para formularios?
¿Cuáles de las siguientes afirmaciones son verdaderas sobre el evento submit y el método submit() de JavaScript para formularios?
Was this page helpful?