2010-02-18 17 views
8

raíz de AP revious question donde le pregunté acerca de cómo deshabilitar un botón de envío hasta que todas las llamadas Ajax ha terminado volviendo ...¿Cómo evito el envío de formularios hasta que hayan finalizado varias llamadas ajax? jQuery

Parece que la gente todavía se las arreglan para enviar el formulario incluso con la tecla bloqueada y una señal de advertencia . Supongo que podría ser presionando 'enter' en una entrada de texto.

¿Cómo hago para deshabilitar todo el formulario, en lugar de solo enviarlo?

El código hasta ahora es:

// if we're waiting for any ajax to complete we need to disable the submit 
$(document).ajaxStart(function() { 
    $(".ajaxbutton").attr("disabled", "disabled"); 
    // if it's taken longer than 250ms display waiting message 
    timer = setTimeout(function() { 
    $('#processingAlert').html(' ...please wait one moment'); 
    $('#processingAlert').show(); 
    }, 250); 
}) 
$(document).ajaxComplete(function() { 
    $(".ajaxbutton").removeAttr("disabled"); 
    $('#processingAlert').hide(); 
    // cancel showing the message when the ajax call completes. 
clearTimeout(timer); 
}); 

Otra cosa que debo mencionar que podría ser la causa de un problema es que hay múltiples llamadas Ajax sucediendo al mismo tiempo, por ejemplo, un div recibe entradas ocultas y otra div en otro lugar en la página muestra un precio total, por ejemplo.

¿El hecho de que algunas llamadas ajax se completen rápidamente anula el efecto de inhabilitación de ajaxStart? EG ajax call1 y ajax call2 encienden el ajaxStart - call1 termina muy rápido, ¿volvería a habilitar el formulario mientras esperamos que call2 se complete?

¿Hay una forma mejor de hacer esto donde podríamos simplemente probar si TODAS las llamadas ajax se han completado?

Respuesta

2

Puede agregar un controlador de eventos para el evento de envío del formulario. El controlador de eventos puede verificar si el envío está permitido todavía, y cancelar si no. Aquí hay algunos documentos: http://api.jquery.com/submit/

Tenga en cuenta que si javascript en la página llama a .click() en uno de los botones de envío de formularios, el formulario se enviará sin llamar a su controlador .submit(). Este es un problema raro de jQuery (http://groups.google.com/group/jquery-en/browse_thread/thread/1317bfd4e3a8b233?pli=1) que supongo que la gente de jQuery no considera un error. Puede haber otros casos como este, espero que no.

Si está utilizando ASP.NET, dependiendo de cuál sea el formulario, ASP.NET puede inyectar una función "__doPostBack". Puede que necesite enganchar esa función redefiniéndola con algún código personalizado que llame al original.

+0

Esto suena en la dirección correcta, desde el manual:. $ ("forma") presente (function() { if ($ ("Entrada: primero"). Val() == "correcta") { $ ("span"). Texto ("Validado ..."). Show(); return true; } $ ("span"). Text ("¡No válido!"). Show(). fadeOut (1000); return false; }); Así que si compruebo que todas las llamadas ajax se completen, puedo devolver la verdad. Estoy usando PHP, por lo que no puedo usar las funciones ASP desafortunadamente. – Ashley

+0

PD ¿Alguien me puede dejar saber cómo insertar el código formateado en un comentario, siempre parezco tener todo aplastado en una línea – Ashley

+0

No creo que pueda formatear el código en los comentarios. Continuaré y ampliaré tu pregunta con comentarios adicionales. –

0

¿Qué hay de crear una variable global:

var i = 0; 

y cada incrementos llamada AJAX esta variable en el inicio de la llamada y lo disminuye cuando se complete.

Al enviar el formulario, verifica si esta variable es mayor que 0 y evita que se envíe.

function submitForm(){ 
     return i == 0; 
    } 

<form onsubmit="submitForm()"....> 

</form> 
+0

Esto suena bastante versátil. En qué puntos de la llamada ajax aumentamos/disminuimos. Es el incremento justo después de $ .ajax ({ – Ashley

+0

) Me imagino que se incrementa al inicio de la función ajaxStart y disminuye al comienzo de la función ajaxComplete –

+0

esto parecía una buena idea, pero cuando lo probé, todos los 3 ajax las llamadas se inician simultáneamente y el contador obtiene un valor de 1. Luego, cuando se completan en diferentes momentos, el contador va a -2. – Ashley

1

Puede simplemente establecer un objeto JS con múltiples propiedades para cada llamada ajax. Ejemplo:

var requiredCalls = {call1: false, call2: false, call3: false} 

En el formulario, envíe un bucle a través de cada propiedad para comprobar si es verdadero. Si alguno es falso, no envíe el formulario.

A medida que completa cada llamada ajax establece su propiedad (call1, call2, etc) en true.

Esa es una forma en que podrías hacerlo, si es la mejor manera, no sé.

+0

Esto suena como una buena idea, sin embargo, hay varias llamadas diferentes que posiblemente se pueden hacer en esta página, no todos son activados por cada cliente. Tendré un pensamiento. – Ashley

+0

en ese caso, si te entiendo correctamente, establecerías sus valores predeterminados en verdadero.Cuando se active la llamada ajax, establecería su propiedad en requiredCalls en false y oncomplete/onsuccess la establecería de nuevo en true. – Mark

0

supongo que hay algo de código como esto:

var form = $(...); 
form.bind ('submit', function (...) { 
    $.ajax (
    ..., 
    complete: function (...) { 
     // do something 
    } 
); 
} 

se puede hacer eso:

var form = $(...); 
form.bind ('submit', function (...) { 
    if ($ (this).data ('inprogress') === null) { 
    $ (this).data ('inprogress', 1); 
    // disable submit button 
    $.ajax (
     ..., 
     complete: function (...) { 
     // do something 
     $ (this).data ('inprogress', null) 
     // enable submit button 
     } 
    ); 
    } else { 
    // display notification/warning 
    } 
} 
0

casi he resuelto esto, pero de alguna manera la gente parece que todavía será capaz de enviar el formulario antes de que las devoluciones de llamada hayan terminado.

No sé si es coincidencia, pero todas las personas que han logrado enviarlo han estado usando Safari en Mac.

Este es el método que estoy usando, sería genial si alguien pudiera detectar el error en la lógica.

El uso de la sugerencia de Vincent:

// set this to zero before any ajax calls are made 
var ajaxcallcounter = 0; 

entonces cuando hago una llamada ajax por ejemplo:

// UPDATE SHIPPING BOXES 
    var data = 'pickup=1'; 
    ajaxcallcounter++; 
    $.ajax({ 
    type: "POST", 
    url: "incViewbasketShippingBoxes.php", 
    data: data, 
    success: function(response) { 
     $('#shippingBoxes').html(response); 
      ajaxcallcounter--; 
    } 
    }); 

Esto está trabajando muy bien, también tienen un pequeño script bueno dar retroalimentación de los usuarios - botón aparece en gris mientras espera que vuelvan los jaxcounters y, si lleva más de 250 ms, también se muestra una animación. Una vez que todas las llamadas Ajax ha completado, el contador vuelve a cero y el botón se muestra como algo normal:

// when ajaxStart is triggered, keep an eye on the ajaxcallcounter 
$(document).ajaxStart(function() { 
    $(".ajaxbutton").attr("disabled", "disabled"); 
    $('#processingAlert').html(' ...calculating'); 
    $('#processingAlert').show(); 

    // if it's taken longer than 250ms (say) display waiting message 
    timer = setTimeout(function() { 
    $('#processingAlert').html(' ...calculating <img src="../gfx-site/ajax-loader.gif">'); 
    }, 250); 
}); 
// when ajaxComplete is triggered, keep an eye on the ajaxcallcounter 
$(document).ajaxComplete(function() { 
    if (ajaxcallcounter == 0) { 
     $(".ajaxbutton").removeAttr("disabled"); 
     $('#processingAlert').hide(); 
     // cancel showing the message when the ajax call completes. 
    clearTimeout(timer); 
    } 
}); 

Por último, llegamos a la función que debe evitar la presentación, pero no parece estar funcionando :

// can we submit yet? 
    $('#checkoutform').submit(function() { 
    if (ajaxcallcounter == 0) { 
     return true; 
    } 
    return false; 
    }); 

¿Alguien puede detectar lo que he hecho mal aquí?

Gracias!

Cuestiones relacionadas