¿Cómo continuar el envío de formularios después de una llamada AJAX?

Quiero validar las entradas de usuario en una publicación de WordPress al presionar el botón de envío, mostrar un mensaje de error si hay problemas y enviar el formulario si todo está bien. Tengo una función de PHP que realiza la comprobación, devolviendo true si los datos en form_data están bien, algún código de error en caso contrario. El siguiente JavaScript emite la solicitud AJAX, y se suponía que debía continuar enviando el formulario luego de una verificación exitosa, pero no lo hace:

  jQuery(document).ready(function() { jQuery('#post').submit(function() { var form_data = jQuery('#post').serializeArray(); var data = { action: 'ep_pre_submit_validation', security: '', form_data: jQuery.param(form_data), }; var proceed = false; jQuery.post(ajaxurl, data, function(response) { if (response.indexOf('true') > -1 || response == true) { proceed = true; } else { alert("Error: " + response); proceed = false; } }); jQuery('#ajax-loading').hide(); jQuery('#publish').removeClass('button-primary-disabled'); return proceed; //breakpoint here makes the code run }); }); 

El código se adaptó de una pregunta WPSE , que originalmente no funcionó para mí ya que el formulario no se envió. Descubrí que si la función jQuery vinculada a .submit() devuelve true, el formulario debería enviarse, así que eso es lo que intenté implementar. Con el código anterior, no parece funcionar al principio (el formulario no se envía cuando no hay errores), pero al inspeccionar de cerca con Firebug, parece que se obtiene el resultado correcto si se inserta un punto de interrupción en la return proceed línea. Funciona según lo previsto con datos válidos solo si lo espero un poco al llegar al punto de interrupción y luego continúo la ejecución. Si hay errores, la alerta se emite sin problemas.

¿Cuál es la mejor manera de manejar esto?

EDITAR

Basado en la respuesta de @Linus a continuación, el siguiente código funciona con datos válidos e inválidos:

  jQuery(document).ready(function() { jQuery('#post').submit(function() { if(jQuery(this).data("valid")) { return true; } var form_data = jQuery('#post').serializeArray(); var data = { action: 'ep_pre_submit_validation', security: '', form_data: jQuery.param(form_data), }; jQuery.post(ajaxurl, data, function(response) { if (response.indexOf('true') > -1 || response == true) { jQuery("#post").data("valid", true).submit(); } else { alert("Error: " + response); jQuery("#post").data("valid", false); } //hide loading icon, return Publish button to normal jQuery('#ajax-loading').hide(); jQuery('#publish').removeClass('button-primary-disabled'); }); return false; }); }); 

Respuesta corta: No puedes, no de esta manera.

Algunos antecedentes: las devoluciones de llamada que proporciona como argumentos a funciones como $.post se ejecutan de forma asíncrona. Esto significa que return proceed antes de que se haya ejecutado su callback exitosa, y el proceso siempre será false . Con su punto de interrupción, si espera hasta que la callback exitosa se haya ejecutado, el proceso será true y todo estará bien.

Por lo tanto, si desea enviar el formulario después de que su solicitud ajax haya finalizado, debe enviarlo usando javascript. Esto es bastante fácil con jQuery, simplemente haga un jQuery $.post con data: $("yourForm").serialize() y url: yourForm.action .

Esto es básicamente lo que ya está haciendo, solo tiene que repetir esa llamada a la URL en la que realmente desea publicar los datos.

EDITAR:

Otra forma sería establecer un atributo en su formulario, por ejemplo, valid , y en su controlador de submit verificar que:

 jQuery("#post").submit(function() { if($(this).data("valid")) { return true; } // Rest of your code }); 

Y en la callback exitosa para su solicitud de validación ajax usted establecería / borraría ese atributo y luego enviaría:

 $("#post").data("valid", true).submit(); 

EDITAR:

También desea hacer su “carga de ajax” / habilitar dentro de la callback por $.post por las mismas razones indicadas anteriormente, tal como están las cosas, sucederán inmediatamente, antes de que su llamada ajax regrese.

Vincule su botón a una función de validación en lugar de enviar. Si pasa la validación, llame a submit ().

WordPress tiene su propio mecanismo para procesar solicitudes Ajax, usando wp-admin / wp-ajax.php. Esto le permite ejecutar código arbitrario a ambos lados del límite de Ajax sin tener que escribir el código de verificación de estado de ida y vuelta y todo eso. Configure sus devoluciones de llamada y vaya ….

La verdadera pregunta es: ¿por qué haces la validación del lado del servidor? ¿Por qué no puedes cargar los criterios de validación antes, ya que la publicación se está escribiendo? Entonces su validación puede ocurrir en tiempo real y no en el momento de la presentación.

jquery.post se realiza de forma asíncrona, lo que significa que JS continuará antes de recibir la respuesta. Está atascado con la respuesta de Diodeus: enlace el botón a la validación que luego envía el formulario (lo que hace que no se degrade bien), o cambie su $ .post a ajax y desactive async, lo que lo obligará a esperar una respuesta antes de continuar … posiblemente bloqueando JS en tu página hasta que se agote el tiempo.

 $.ajax({ type: 'POST', url: ajaxurl, async:false, data: data, timeout:3000, success: function(){ } });