forma form javascript c# jquery asp.net-mvc asp.net-mvc-5

javascript - forma - Espere a que form.submit()/POST se complete



submit form javascript (1)

Estoy atrapado en una situación realmente extraña aquí. Es complicado de explicar, pero lo intentaré lo mejor posible.

Explicación detallada del problema:

En cada clic superior de Nav (Donas / círculos verdes), o en el siguiente botón, debo enviar el formulario, si existe y es válido. Si no es válido, form.valid () desencadena errores de validación y return false detendría cualquier propagación adicional. Esta configuración funcionaba perfectamente hasta que noté un comportamiento extraño que no es muy persistente. El formulario en mi tercera pestaña, específicamente, es bastante pesado. Cuando presiono el botón siguiente, prácticamente debería pasar por el mismo proceso: busque un formulario existente, si es válido, luego envíe. Enviar llamadas al método de acción POST y cuando se completa la publicación GET obtiene la vista para la siguiente pestaña. Funciona así 5/10 veces, pero en otras ocasiones GET se ejecuta antes del POST, lo que hace que la página siguiente cargue con datos incompletos. Cuando puse breakpoints para depurar, veo GET para la siguiente pestaña que se ejecuta antes del POST de la pestaña actual.

IU explicada:

Tengo una IU con 4 botones de navegación <a> en la parte superior, en el centro siempre hay un formulario y en la parte inferior tengo los botones Anterior y Siguiente.

Los formularios se construyen en MVC usando Ajax.BeginForm

Para cada elemento de enlace de <a> en la parte superior, tengo una función de JavaScript

var LoadTabs = function (e, arg) { // This is to validate a form if one of the top links is clicked and form has incomplete fields... if (arg !== "prev" && arg !== "next") { if (!window.ValidateForm(false)) return false; } var url = $(this).attr(''data''); // this contains link to a GET action method if (typeof url != "undefined") { $.ajax(url, { context: { param: arg } }).done(function (data) { $(''#partialViewContainer'').html(data); }); } }

Esta función anterior se une a cada enlace superior en la carga de la página.

$(''.navLinks'').on(''click'', LoadTabs);

Mis botones Siguiente y Anterior básicamente activan el evento click, es decir, la función LoadTabs .

$(''button'').on(''click'', function () { if (this.id === "btnMoveToNextTab") { if (!window.ValidateForm(true)) return false; $.ajax({ url: url, context: { param: ''next'' }, method: "GET", data: data, success: function(response) { if (typeof response == ''object'') { if (response.moveAhead) { MoveNext(); } } else { $(''#mainView'').html(response); } ScrollUp(0); } }); } if (this.id === "btnMoveToPreviousTab") { MoveBack(); } return false; }); MoveNext() Implementation is as below: function MoveNext() { var listItem = $(''#progressbarInd > .active'').next(''li''); listItem.find(''.navLink'').trigger(''click'', [''next'']); ScrollUp(0); }

El problema es que, por alguna razón, cuando Nav Link 3 está activo y presiono el botón NEXT - En lugar de publicar el formulario primero a través de form.submit (), se activa el nav 4, de ahí GET para nav 4 runs antes de la forma POST de nav 3.

Mi método ValidateForm básicamente está comprobando si el formulario existe y es válido luego Enviar, de lo contrario devuelve falso. Es como a continuación:

function ValidateForm(submit) { var form = $(''form''); // if form doesn''t exist on the page - return true and continue if (typeof form[0] === "undefined") return true; // now check for any validation errors if (submit) { if (!$(form).valid()) { return false; } else { $(form).submit(); } } else { return true; } return true; }

Mi especulación es que form.submit se desencadena como debería ser, pero como el envío tarda un poco más en finalizar, continúa con el siguiente bloque de código en el evento onclick del botón.

Primero pensé que este es un problema del lado del servidor ya que en el POST estoy guardando una gran cantidad de datos con algunos bucles, y cualquier bloque de código que sea pesado en el proceso tengo esa parte en

var saveTask = Task.Factory.StartNew(() => ControllerHelper.SomeMethod(db, model)); Task.WaitAll(saveTask);

WaitAll esperará y pausará la ejecución hasta que SomeMethod termine de ejecutarse. No estoy seguro de cómo puedo bloquear un proceso en JavaScript y esperar a que finalice la ejecución. Porque creo que si de alguna manera puedo bloquear el formulario.submit () en ValidateForm hasta su procesamiento final ... a través de un método de devolución de llamada tal vez ...

Por favor, si alguien puede ponerme en la dirección correcta, agradecería mucho la ayuda. Si necesita más información, ¡hágamelo saber que nos complacerá brindarle!


Ajax es asincrónico, y tus formularios envían lo que está usando Ajax.BeginForm() está usando ajax. Lo que está sucediendo es que cuando haces clic en el botón ''Siguiente'', que activa el $(''button'').on(''click'', function () { código:

  1. Usted llama a la función ValidateForm() (y asumiendo que es válida), su $(form).submit(); línea de código comienza a hacer un POSTE ajax
  2. El código progresa al return true; final return true; línea mientras se está ejecutando la llamada ajax.
  3. Como la función ValidateForm() devolvió verdadero, ahora se inicia la llamada $.ajax GET, pero en ese momento la POST ajax en la función ValidateForm() puede no haber terminado de ejecutarse, lo que hace que su método GET devuelva datos no válidos.

Debe cambiar su código para que la llamada GET se realice una vez que se haya completado la llamada al método POST. Y como usa los métodos $.ajax() todo su código, y $.ajax() le da más flexibilidad, parece innecesario usar Ajax.BeginForm() (y la sobrecarga adicional de incluir jquery.unbtrusive-ajax.js script). También debería manejar la función de formularios .submit() (si no desea que el botón ''Siguiente'' sea un botón de enviar en el formulario, puede desencadenar el evento .submit() en los botones .click() handler )

$(document).on(''submit'', ''form'', function(e) { e.preventDefault(); // cancel default submit var form = $(this); if (!form.valid()) { return; // will display the validation errors } .... // get the relevant urls to the GET and POST methods etc $.post(postUrl, form.serialize(), function(data) { .... // not clear if your [HttpPost] method returns anything }).done(function() { $.get(getUrl, someData, function(response) { .... // Update the DOM with the next form? .... // Re-parse the validator for client side validation } }).fail(function() { .... // code that you might run if the code in the [HttpPost] method fails }); });

También debería considerar devolver la vista ''siguiente'' apropiada en el método [HttpPost] para que luego no tenga que volver a hacer una segunda llamada al servidor para obtenerla.

También vale la pena leer la documentación del Objeto Diferido y el uso de $.when() , $.then() etc.