¿Cómo hacer una devolución de llamada de Jquery después de enviar el formulario?

119

Tengo una forma simple con remote = true.

Este formulario está en realidad en un cuadro de diálogo HTML, que se cierra tan pronto como se hace clic en el botón Enviar.

Ahora necesito hacer algunos cambios en la página HTML principal después de que el formulario se envíe correctamente.

Intenté esto usando jQuery. Pero esto no garantiza que las tareas se realicen después de alguna forma de respuesta al envío del formulario.

$("#myform").submit(function(event) {

// do the task here ..

});

¿Cómo adjunto una devolución de llamada para que mi código se ejecute solo después de que el formulario se haya enviado correctamente? ¿Hay alguna forma de agregar alguna devolución de llamada .success o .complete al formulario?

geek_monster
fuente
¿Por qué no usas Ajax? Con las funciones de jQuery Ajax puede definir tales devoluciones de llamada.
Davidbuzatto
12
davidbuzatto, hay algunos casos en los que no puede usar ajax. Por ejemplo, cuando desee cargar un archivo.
Pere
3
@Pere No es cierto aquí en el futuro.
SparK

Respuestas:

119

Acabo de hacer esto

 $("#myform").bind('ajax:complete', function() {

         // tasks to do 


   });

Y las cosas funcionaron perfectamente.

Consulte esta documentación de la API para obtener detalles más específicos.

geek_monster
fuente
3
Vaya ... acabo de aprender algo nuevo. Sí, por lo que parece, esta es la solución más simple. Quizás, es incluso el mejor. Soy un ávido lector de Coding Horror, y en ese blog, Jeff Attwood enfatiza que deberíamos escribir menos código, y este método lo logra. Buen descubrimiento. :)
Sal
7
¿Y si <form>se presenta habitualmente? (Me refiero a que no con Ajax) ¿Qué puedo poner en el primer argumento .bind()? EDITAR: bueno, supongo click. Nvm, lo siento. : p
4wk_
9
cuidado: esto activará su función después de la finalización de cualquier evento ajax, no solo el envío de su formulario (a menos que me equivoque, en cuyo caso me encantaría que proporcionara un enlace donde lo encontró)
DMac the Destroyer
18
"A partir de jQuery 1.8, el método .ajaxComplete () solo debe adjuntarse al documento"
Meredith
6
No funcionó conmigo, usando el formulario normal, con un botón, pero el botón llama a javascript $ ('# formFile'). Submit ();
Daniel
35

No pude hacer que la solución número uno con voto positivo funcionara de manera confiable, pero descubrí que funciona. No estoy seguro de si es necesario o no, pero no tengo un atributo de acción o método en la etiqueta, lo que garantiza que la función $ .ajax maneje el POST y le brinda la opción de devolución de llamada.

<form id="form">
...
<button type="submit"></button>
</form>

<script>
$(document).ready(function() {
  $("#form_selector").submit(function() {

    $.ajax({
     type: "POST",
      url: "form_handler.php",
      data: $(this).serialize(),
      success: function() {
        // callback code here
       }
    })

  })
})
</script>
Bradley Bossard
fuente
1
+1. La clave de esta respuesta es la $(this).serialize()línea. Te permite jQuery.ajax()enviar el formulario existente en segundo plano, luego capturar la respuesta del servidor y hacer algo con ella.
Warren Young
15
javascript sin punto y coma ... algunas personas solo quieren ver arder el mundo. Sin embargo, su solución funciona, así que gracias :)
viggity
2
Tenga en cuenta que .serializeno incluye entradas de archivo en su solicitud POST. Use HTML5 FormData (consulte esta pregunta ) en su lugar, a menos que sea compatible con navegadores antiguos como IE <9
brichins
Apoyos para usar $(this).serialize(), ¡resolvió mis problemas!
gnclmorais
¿Qué es 'form_selector' en su html al que hace referencia en el js?
Kevin Meredith
23

Tendrá que hacer las cosas manualmente con una llamada AJAX al servidor. Esto requerirá que también anule el formulario.

Pero no te preocupes, es pan comido. Aquí hay una descripción general de cómo trabajará con su formulario:

  • anular la acción de envío predeterminada (gracias al objeto de evento pasado, que tiene un preventDefaultmétodo)
  • tomar todos los valores necesarios del formulario
  • disparar una solicitud HTTP
  • manejar la respuesta a la solicitud

Primero, tendrá que cancelar la acción de envío del formulario así:

$("#myform").submit(function(event) {
    // Cancels the form's submit action.
    event.preventDefault();
});

Y luego, tome el valor de los datos. Supongamos que tiene un cuadro de texto.

$("#myform").submit(function(event) {
    event.preventDefault();
    var val = $(this).find('input[type="text"]').val();
});

Y luego dispara una solicitud. Supongamos que es una solicitud POST.

$("#myform").submit(function(event) {
    event.preventDefault();
    var val = $(this).find('input[type="text"]').val();

    // I like to use defers :)
    deferred = $.post("http://somewhere.com", { val: val });

    deferred.success(function () {
        // Do your stuff.
    });

    deferred.error(function () {
        // Handle any errors here.
    });
});

Y esto debería ser suficiente.

Nota 2: para analizar los datos del formulario, es preferible que utilice un complemento . Hará su vida realmente fácil, además de proporcionar una buena semántica que imita una acción de envío de formulario real.

Nota 2: no es necesario utilizar diferidos. Es solo una preferencia personal. También puede hacer lo siguiente, y también debería funcionar.

$.post("http://somewhere.com", { val: val }, function () {
    // Start partying here.
}, function () {
    // Handle the bad news here.
});
Sal
fuente
2
Gran muestra. ¿Cómo hacer lo mismo con la carga de archivos (varias partes / datos de formulario)?
Adam W
11

Para MVC, este era un enfoque aún más fácil. Necesita usar el formulario Ajax y configurar las opciones Ajax

@using (Ajax.BeginForm("UploadTrainingMedia", "CreateTest", new AjaxOptions() { HttpMethod = "POST", OnComplete = "displayUploadMediaMsg" }, new { enctype = "multipart/form-data", id = "frmUploadTrainingMedia" }))
{ 
  ... html for form
}

aquí está el código de envío, se encuentra en la sección de preparación del documento y vincula el evento onclick del botón para enviar el formulario

$("#btnSubmitFileUpload").click(function(e){
        e.preventDefault();
        $("#frmUploadTrainingMedia").submit();
});

aquí está la devolución de llamada a la que se hace referencia en AjaxOptions

function displayUploadMediaMsg(d){
    var rslt = $.parseJSON(d.responseText);
    if (rslt.statusCode == 200){
        $().toastmessage("showSuccessToast", rslt.status);
    }
    else{
        $().toastmessage("showErrorToast", rslt.status);
    }
}

en el método del controlador para MVC se ve así

[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult UploadTrainingMedia(IEnumerable<HttpPostedFileBase> files)
{
    if (files != null)
    {
        foreach (var file in files)
        {
            // there is only one file  ... do something with it
        }
        return Json(new
        {
            statusCode = 200,
            status = "File uploaded",
            file = "",
        }, "text/html");
    }
    else
    {
        return Json(new
        {
            statusCode = 400,
            status = "Unable to upload file",
            file = "",
        }, "text/html");
    }
}
edepperson
fuente
2
Esos códigos son códigos .Net y en la pregunta nunca se especificó.
MrMins
13
Esa realmente no es una buena razón para rechazar esto. La respuesta funciona y podría ayudar a un desarrollador de .NET que se enfrenta al mismo problema.
edepperson
Me gusta esta idea, pero por alguna razón la devolución de llamada no se activa. ¿El método del controlador tiene que devolver un JsonResult? Mi método de controlador actualmente devuelve un ActionResult.
Mattpm
7

No creo que haya una función de devolución de llamada como la que describe.

Lo normal aquí es hacer las alteraciones usando algún lenguaje del lado del servidor, como PHP.

En PHP, por ejemplo, podría buscar un campo oculto de su formulario y hacer algunos cambios si está presente.

PHP:

  $someHiddenVar = $_POST["hidden_field"];
    if (!empty($someHiddenVar)) {
        // do something 
    }

Una forma de hacerlo en Jquery es usar Ajax. Puede escuchar enviar, devolver falso para cancelar su comportamiento predeterminado y usar jQuery.post () en su lugar. jQuery.post tiene una devolución de llamada exitosa.

$.post("test.php", $("#testform").serialize(), function(data) {
  $('.result').html(data);
});

http://api.jquery.com/jQuery.post/

Sindre
fuente
0

Los controladores "al enviar" del formulario se llaman antes de enviar el formulario. No sé si hay un controlador al que llamar después de enviar el formulario. En el sentido tradicional que no es Javascript, el envío del formulario recargará la página.

anguila ghEEz
fuente
A menos que el envío del formulario redirija a la descarga de un archivo, en cuyo caso la página se deja intacta. No puedo usar el envío de JavaScript porque una solicitud Ajax no puede iniciar la descarga de un archivo (sin juegos de etiquetas de anclaje), pero tampoco puedo decirle al usuario que espere o limpie una vez que tenga el archivo ...
kitsu .eb
-1
$("#formid").ajaxForm({ success: function(){ //to do after submit } });
Aikanáro
fuente
3
¿Es ajaxForm()un componente de terceros que ha instalado? No es una parte estándar de jQuery.
Warren Young