jQuery / Method / .submit() — Eventos de envío de formularios

Maneje el envío con $(form).on("submit", handler). Para solicitarlo mediante validación del navegador, use form.requestSubmit(). El antiguo atajo jQuery .submit(), el disparo de eventos y form.submit() nativo tienen rutas distintas.

Conectar frente a solicitar envío

El atajo jQuery .submit() está obsoleto desde 3.3. Con función conecta; sin argumentos dispara. Ambos existen en las versiones completas probadas 3.7.1 y 4.0.0. Para código nuevo prefiera API explícitas; obsoleto no significa eliminado automáticamente.

El evento submit pertenece al formulario. Allí cubre clic, Enter y solicitud programada. Validar solo en el clic de un botón puede omitir otras rutas.

Ruta Validación y evento Uso
.on("submit", handler) Conecta sin enviar Manejar el evento
Botón submit / requestSubmit() Restricciones, luego submit si es válido Solicitud normal
jQuery .trigger("submit") No reproduce la misma validación nativa Disparo deliberado
form.submit() nativo Omite restricciones y evento Omisión especial intencionada

Ejemplo completo comparativo

Guarde y abra submit-demo.html en UTF-8. Internet carga jQuery completo 4.0.0, sin servidor ni compilación. preventDefault detiene todo envío y solo muestra resultados. No hay transmisión externa ni almacenamiento. Windows Edge con 4.0.0 y 3.7.1 comprobó rutas y datos del botón.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Inspect form submit events</title>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
  <style>
    body { font: 16px/1.6 sans-serif; max-width: 720px; margin: 20px; }
    label { display: block; margin-top: 12px; }
    input, select, button { font: inherit; max-width: 100%; margin: 5px 0; }
    pre { white-space: pre-wrap; overflow-wrap: anywhere; }
  </style>
</head>
<body>
  <form id="chooser">
    <label for="person">Name</label>
    <input id="person" name="person" required>
    <label for="fruit">Fruit</label>
    <select id="fruit" name="fruit" required>
      <option value="">Choose a fruit</option>
      <option value="apple">Apple</option><option value="banana">Banana</option>
    </select>
    <button id="inside" type="submit" name="intent" value="inside">Inspect inside</button>
  </form>
  <button id="outside" type="submit" form="chooser" name="intent" value="outside">Inspect outside</button>
  <button id="request" type="button">requestSubmit(inside)</button>
  <button id="trigger" type="button">jQuery trigger submit</button>
  <button id="restore" type="button">Reset</button>
  <label><input id="automatic" type="checkbox">Request submission when fruit changes</label>
  <pre id="result" aria-live="polite">events=0
No submission inspected.</pre>
  <script>
    jQuery(function ($) {
      const form = document.querySelector("#chooser");
      let events = 0;
      $(form).on("submit", function (event) {
        event.preventDefault(); events++;
        if (!form.reportValidity()) {
          $("#result").text("events=" + events + "\nInvalid data; not inspected."); return;
        }
        const submitter = event.originalEvent ? event.originalEvent.submitter : null;
        const data = submitter ? new FormData(form, submitter) : new FormData(form);
        $("#result").text("events=" + events + "\nsubmitter=" + (submitter ? submitter.id : "(none)") +
          "\nvalues=" + JSON.stringify(Object.fromEntries(data)));
      });
      $("#request").on("click", function () { form.requestSubmit(document.querySelector("#inside")); });
      $("#trigger").on("click", function () { $(form).trigger("submit"); });
      $("#fruit").on("change", function () {
        if (document.querySelector("#automatic").checked) form.requestSubmit();
      });
      $("#restore").on("click", function () {
        form.reset(); document.querySelector("#automatic").checked = false; events = 0;
        $("#result").text("events=0\nNo submission inspected.");
      });
    });
  </script>
</body>
</html>

Estado inicial: events cuenta entradas al manejador, no guardados correctos en servidor.

events=0
No submission inspected.
  1. Con campos vacíos, inside, outside y requestSubmit(inside) quedan bloqueados por required: events=0.
  2. jQuery trigger submit alcanza events=1, pero reportValidity muestra Invalid data; not inspected.
  3. Reset, JB y Apple, luego Inspect inside: events=1, submitter=inside y valores del formulario.
  4. Inspect outside da submitter=outside e intent=outside. form="chooser" asocia el botón externo.
  5. requestSubmit(inside) especifica ese botón. Enter en Name también usa aquí el primero, inside.
  6. El disparo jQuery válido muestra submitter=(none), sin intent de botón.
  7. Active solicitud automática y cambie a Banana: requestSubmit() sin botón da submitter=(none).
  8. Reset restaura valores, casilla automática y contador.

event.originalEvent.submitter lee el botón del SubmitEvent nativo. Un evento jQuery sintético puede no tener originalEvent. FormData(form, submitter) incluye su name/value. Object.fromEntries conserva solo el último valor de nombres repetidos; esta visualización no sirve para recopilar arrays sin adaptarla.

Controles externos y prevención

Un button type="submit" real con atributo form ofrece comportamiento de teclado y formulario incluso fuera. Esa posición no omite required por sí sola; importa la API elegida.

requestSubmit() valida y emite submit si procede. El elemento especificado debe ser un botón de envío asociado al formulario. El ejemplo muestra ambas variantes.

Enviar en cada cambio de select puede sorprender al elegir con flechas. Aquí debe activarse expresamente y no hay navegación. Decida entre filtro inmediato y confirmación. Un setter .val() por sí solo no emite change.

preventDefault detiene el envío normal. Para esperar trabajo asíncrono, prevéngalo durante el manejador; tras await no se deshace un envío iniciado. No hay transporte asíncrono en este ejemplo. Una implementación real necesita estado en curso, duplicados, recuperación y validación del servidor.

Atajo antiguo y método nativo

Ejecute esta comprobación tras inicializar. El formulario separado impide la acción predeterminada sin solicitud de servidor.

const $probe = $("<form>");
let calls = 0;
$probe.submit(function (event) {
  event.preventDefault();
  calls++;
});
$probe.submit();
console.log("legacy calls=" + calls);

Resultado Console; en código antiguo distinga función y llamada sin argumentos.

legacy calls=1

.trigger("submit") ejecuta manejadores y puede continuar al método nativo si no se impide. No simula completamente clic y restricciones. reportValidity protege también el caso sintético del ejemplo.

HTMLFormElement.submit() omite restricciones y manejadores. Otra prueba envió un required vacío a un iframe interceptando localmente la solicitud: datos vacíos y cero eventos. No comprobó almacenamiento en un servidor receptor real.

Ante form.submit is not a function, busque un control con name o id submit que oculte el método. Evite también reset. Distinga colección jQuery y formulario DOM: requestSubmit pertenece al DOM, accesible por ejemplo mediante [0].

El envío real requiere action, method y receptor adecuados; adapte la prevención permanente y visualización de la práctica. Valid no significa guardado y required no sustituye controles del servidor.