Interceptar el envío de un formulario en JavaScript y evitar el envío normal

84

Parece haber mucha información sobre cómo enviar un formulario usando javascript, pero estoy buscando una solución para capturar cuándo se ha enviado un formulario e interceptarlo en javascript.

HTML

<form>
 <input type="text" name="in" value="some data" />
 <button type="submit">Go</button>
</form>

Cuando un usuario presiona el botón Enviar, no quiero que se envíe el formulario, sino que me gustaría que se llamara a una función de JavaScript.

function captureForm() {
 // do some stuff with the values in the form
 // stop form from being submitted
}

Un truco rápido sería agregar una función onclick al botón, pero no me gusta esta solución ... hay muchas formas de enviar un formulario ... por ejemplo, presionando retorno mientras está en una entrada, lo que esto no tiene en cuenta.

Ty

mrwooster
fuente
3
Posible duplicado de ¿Cómo evitar que se envíe el formulario?
Michał Perłakowski

Respuestas:

96
<form id="my-form">
    <input type="text" name="in" value="some data" />
    <button type="submit">Go</button>
</form>

En JS:

function processForm(e) {
    if (e.preventDefault) e.preventDefault();

    /* do what you want with the form */

    // You must return false to prevent the default form behavior
    return false;
}

var form = document.getElementById('my-form');
if (form.attachEvent) {
    form.attachEvent("submit", processForm);
} else {
    form.addEventListener("submit", processForm);
}

Editar : en mi opinión, este enfoque es mejor que establecer el onSubmitatributo en el formulario, ya que mantiene la separación del marcado y la funcionalidad. Pero esos son solo mis dos centavos.

Edit2 : actualicé mi ejemplo para incluirpreventDefault()

Michael McTiernan
fuente
esto tampoco funciona con Chrome, por lo que puedo ver usando jsbin.com/ejoyas
Eiyrioü von Kauyf
2
Tenga en cuenta que el código de evento adjunto debe ejecutarse DESPUÉS de que el formulario esté disponible en dom. Por ejemplo, usando window.onload=function() { ... }para envolverlo
mplungjan
¿Cuándo processform()se llama a la función señor?
No estoy seguro porque no uso IE, pero creo que el parámetro attachEvent debería ser "onsubmit".
Gerard ONeill
esto no funciona en Chrome 46, error al adjuntar un evento, es necesario cargar la página primero
tsukimi
28

No puede adjuntar eventos antes de que los elementos a los que los adjunta se hayan cargado

Esto funciona -

JS simple

MANIFESTACIÓN

Recomendado para usar eventListener

// Should only be triggered on first page load
console.log('ho');

window.addEventListener("load", function() {
  document.getElementById('my-form').addEventListener("submit", function(e) {
    e.preventDefault(); // before the code
    /* do what you want with the form */

    // Should be triggered on form submit
    console.log('hi');
  })
});
<form id="my-form">
  <input type="text" name="in" value="some data" />
  <button type="submit">Go</button>
</form>

pero si no necesita más de un oyente, puede usar onload y onsubmit

// Should only be triggered on first page load
console.log('ho');

window.onload = function() {
  document.getElementById('my-form').onsubmit = function() {
    /* do what you want with the form */

    // Should be triggered on form submit
    console.log('hi');
    // You must return false to prevent the default form behavior
    return false;
  }
}
    <form id="my-form">
      <input type="text" name="in" value="some data" />
      <button type="submit">Go</button>
    </form>

jQuery

// Should only be triggered on first page load
console.log('ho');

$(function() {
  $('#my-form').on("submit", function(e) {
    e.preventDefault(); // cancel the actual submit

    /* do what you want with the form */

    // Should be triggered on form submit

    console.log('hi');
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="my-form">
  <input type="text" name="in" value="some data" />
  <button type="submit">Go</button>
</form>

mplungjan
fuente
Creo que te refieres a: $ ('# mi-formulario) .on (' enviar ', función () {alerta (' hola ');});
Michiel
1
@Michiel, si bien lo que proporciona es lo que usa con jQuery, esta solución proporcionada es una solución JS pura sin dependencia de jQuery. La solución aquí sería similar a usar<form onsubmit="alert('hi'); return false;">
Chris Marisic
2
@ChrisMarisic - algunos años :) He actualizado la respuesta de todos modos para incluir jQuery
mplungjan
17

<form onSubmit="return captureForm()"> eso debería hacer. Asegúrese de que su captureForm()método regrese false.

kba
fuente
Seguimiento: ¿Hay alguna forma de capturar un envío de formulario con JavaScript sin afectar el manejo del navegador del atributo requerido?
Elisabeth
@Elisabeth ¿Qué manejo de qué atributo? Si no quiere evitar que el formulario se envíe realmente, solo debe captureForm()regresar en truelugar de false.
kba
El manejo del navegador del atributo "requerido". Quiero evitar que se envíe el formulario. Pero al devolver falso en lugar de verdadero (o usar preventDefault ()), cambia la forma en que el navegador maneja el atributo "requerido" en un elemento de entrada. Pruébelo usted mismo: agregue <code> required </code> a un elemento de entrada, capture el envío y vea si pierde el comportamiento predeterminado.
Elisabeth
No parece que pierda el comportamiento predeterminado. Funciona bien en Chrome. Deberá dar un ejemplo erróneo para que pueda ayudar.
kba
1
Ok, aquí está el formulario: <form method = "get" action = ""> <label for = "color"> ¿Cuál es tu color favorito? </label> <input type = "text" name = "color" placeholder = "blue" required> <input id = "submit" type = "submit" value = "Submit"> </form> y aquí está el código: function processForm (e) {var form = document.querySelector ("form"); for (var i = 0; i <form.childNodes.length; i ++) {var nodo = form.childNodes [i]; / * hacer cosas con los nodos /} / return false; * /} Pruebas en opera. Quite el comentario de la última línea, los errores obligatorios. (Lo siento, el código no funciona bien en los comentarios)
Elisabeth
6

Otra opción para manejar todas las solicitudes que utilicé en mi práctica para los casos en que onload no puede ayudar es manejar solicitudes de javascript, html y ajax. Este código debe agregarse en la parte superior del elemento del cuerpo para crear un oyente antes de que se procese y envíe cualquier formulario.

En el ejemplo, configuro el campo oculto para cualquier formulario en la página en su envío, incluso si ocurre antes de la carga de la página.

//Handles jquery, dojo, etc. ajax requests
(function (send) {
    var token = $("meta[name='_csrf']").attr("content");
    var header = $("meta[name='_csrf_header']").attr("content");
    XMLHttpRequest.prototype.send = function (data) {
        if (isNotEmptyString(token) && isNotEmptyString(header)) {
            this.setRequestHeader(header, token);
        }
        send.call(this, data);
    };
})(XMLHttpRequest.prototype.send);


//Handles javascript submit
(function (submit) {
    HTMLFormElement.prototype.submit = function (data) {
        var token = $("meta[name='_csrf']").attr("content");
        var paramName = $("meta[name='_csrf_parameterName']").attr("content");
        $('<input>').attr({
            type: 'hidden',
            name: paramName,
            value: token
        }).appendTo(this);

        submit.call(this, data);
    };
})(HTMLFormElement.prototype.submit);


//Handles html submit
document.body.addEventListener('submit', function (event) {
    var token = $("meta[name='_csrf']").attr("content");
    var paramName = $("meta[name='_csrf_parameterName']").attr("content");
    $('<input>').attr({
        type: 'hidden',
        name: paramName,
        value: token
    }).appendTo(event.target);
}, false);
Vitaliy Borisok
fuente
2

Use la respuesta de @Kristian Antonsen, o puede usar:

$('button').click(function() {
    preventDefault();
    captureForm();
});
rsplak
fuente
3
para cualquier otra persona que haga esto 2.5 años (o más) después, debe pasar el evento de clic como un parámetro a la función (como en function(e)y llamare.preventDefault()
digitaljoel
También se puede capturar en el evento "enviar" para el formulario, si se utiliza su entrada [tipo = "enviar"], y eso lo coloca en el contexto del formulario frente al contexto del botón. La devolución de llamada siempre tendrá el contexto del evento, por lo que no necesariamente tiene que pasar 'e' como argumento, simplemente se refiere a 'evento'.
augurone
1
Esto no se recomienda, ya que el envío se puede activar al presionar una tecla.
jhpratt