Esta es una entrada bastante técnica, pero que puede ser de gran utilidad para quienes estén enfrentados al problema de enviar datos de un formulario por Jquery Ajax y se le dupliquen los post, más aún si están usando un modal de Bootstrap. ¿Qué?

Bueno, para entrar en contexto, te contamos que dentro de nuestras funciones de desarrollo web, más a menudo de lo que quisiéramos, nos encontramos con pequeñas batallas que nos dejan “parados” por decirlo de alguna forma, y nos obligan a buscar y rebuscar en Google y preguntarle a cuánto contacto tengamos a mano para ver si tienen alguna idea de cómo solucionar el inconveniente y eso fue más o menos lo que nos sucedió a inicios de este mes.

En el caso que detallamos a continuación, uno de nuestros clientes utilizaba una tabla de resultados donde cada registro tenía un botón para cambiar uno de sus valores. Por ejemplo, habían 20 clientes que aparecían con cuentas sin pagar, y se quería modificar una fila para indicar que ya había pagado.

Hasta ahí todo bien y lo solucionamos con un código más o menos así:

$(function(){ //abreviación de document.ready...

$("#id_del_boton").click(function(e){

e.preventDefault(); //anulamos la acción por defecto del botón

var dato1 = $("#id_del_boton").attr("data-algo");

$.ajax(...); //acá va la acción que envía por POST los datos...

}

});

El html del botón era algo así:

<button id=”id_del_boton” data-algo=”valor_del_boton”>texto</button>

Lo anterior funcionaba perfectamente, siempre y cuando se hiciera una única petición por página. Si recargábamos la página original, podíamos ingresar el siguiente dato y así sucesivamente, pero esa no era la gracia si se quería hacer por ajax. El problema comenzó cuando tuvimos que ingresar más de un pago en el mismo momento. El segundo clic enviaba 2 post por ajax. En palabras simples, como que el primer post se quedaba en caché y se volvía a enviar. Si enviábamos 3 veces, entonces se hacían 3 post. El problema es que en la base de datos quedaba todo mal guardado ya que el último post sobrescribía el anterior y el anterior…

Buscando una solución nos encontramos con el siguiente enlace:

http://stackoverflow.com/questions/2959640/stop-duplicate-ajax-submisions

Hasta ahí todo bien, pero lamentablemente no nos funcionaba porque teníamos un botón anterior que llamaba al formulario en una ventana modal.

$(function(){ //abreviación de document.ready...

$("#id_boton_modal").click(function(){ //Lanzamos el modal
$('#myModal').modal('show');
$("#id_del_boton").click(function(e){

e.preventDefault(); //anulamos la acción por defecto del botón

var dato1 = $("#id_del_boton").attr("data-algo");

$.ajax(...); //acá va la acción que envía por POST los datos...

}

});//final del id_del_boton click

});//final del modal click

Entonces, luego de intentar las soluciones encontradas en la red, y de cabecearnos un poco nos dimos cuenta que el parche había que hacerlo en el primer clic, es decir en el que levanta el modal. (Suena lógico pero después de la batalla todos son generales)

Entonces comenzamos la solución:

Paso 1: Definimos una variable cualquiera, en este caso llamada “request” justo antes del primer click.

 $(document).ready(function () {
        var request;
        $("#id_boton_modal").click(function () {//... etc

Paso 2: Antes de llamar al $.ajax lo cambiamos por lo siguiente:

if (!request) { request = $.ajax(
{ type: "POST", 
url: "/datos/modificar_estado.php", //procesa y devuelve un json
data: { id: dato1, estado: "texto", nota: "texto"}, 
success: function (data) {
 var nuevoe = $.parseJSON(data);
 var nuevoestado = nuevoe.estado; //nuevow-estado es un resultado capturado vía Json en la respuesta del php que hizo la pega
  $('#myModal').modal('hide');//acá cierro el modal
},
 error: function () { alert("Se ha producido un error"); },
 complete: function () { request = null } }); //esta es la magia
 }//fin del if request
});
request = null; //esto va fuera del ajax pero dentro del click que lo detona

Luego cierro el click del modal y el click del document.ready y estamos listos!

No hay comentarios