javascript - form - input type submit onclick



Warten Sie, bis form.submit()/POST abgeschlossen ist (1)

Ajax ist async und Ihre Formulare, die Ajax.BeginForm() verwenden, verwenden Ajax.BeginForm() . Was passiert, wenn Sie auf die Schaltfläche 'Weiter' klicken, die das $('button').on('click', function () { auslöst $('button').on('click', function () { code:

  1. Sie rufen die ValidateForm() Funktion auf (und gehen davon aus, dass sie gültig ist), Ihre $(form).submit(); Codezeile fängt an, einen AJAX POST zu machen
  2. Der Code wird bis zur endgültigen return true; während der Ajax-Aufruf ausgeführt wird.
  3. Da die ValidateForm() Funktion True $.ajax , wird jetzt der $.ajax GET-Aufruf $.ajax , aber zu diesem Zeitpunkt ist der AJAX-POST in der ValidateForm() Funktion möglicherweise noch nicht fertig ausgeführt, wodurch Ihre GET-Methode ungültige Daten $.ajax

Sie müssen Ihren Code ändern, damit der GET-Aufruf ausgeführt wird, sobald der POST-Methodenaufruf abgeschlossen ist. Und da Sie die $.ajax() -Methoden im gesamten Code verwenden und $.ajax() mehr Flexibilität bietet, scheint es unnötig zu sein, Ajax.BeginForm() (und den zusätzlichen Aufwand, den jquery.unbtrusive-ajax.js Skript). Sie sollten auch die Funktion .submit() . Wenn Sie nicht möchten, dass die Schaltfläche 'Weiter' eine Übergabeschaltfläche im Formular ist, können Sie einfach das Ereignis .submit() im buttons .click() Handler auslösen )

$(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
    });
});

Sie sollten auch in Betracht ziehen, die entsprechende 'nächste' Ansicht in der [HttpPost] -Methode zurückzugeben, sodass Sie dann keinen zweiten Aufruf an den Server [HttpPost] müssen, um ihn zu erhalten.

Es lohnt sich auch, die Deferred Object-Dokumentation und die Verwendung von $.when() , $.then() usw. zu $.then() .

Ich stehe hier in einer wirklich bizarren Situation fest. Es ist kompliziert zu erklären, aber ich werde mein Bestes geben.

Detaillierte Erklärung des Problems:

Auf jedem oberen Nav-Klick (Grüne Donuts / Kreise) oder Next Button muss ich das Formular einreichen, sofern es existiert und gültig ist. Wenn sie nicht gültig ist, löst form.valid () Validierungsfehler aus, und die Rückgabe von false würde jede weitere Weitergabe stoppen. Dieses Setup funktionierte einwandfrei, bis ich ein seltsames Verhalten bemerkte, das nicht sehr persistent ist. Das Formular auf meiner 3. Registerkarte ist besonders datenintensiv. Wenn ich den nächsten Knopf drücke, sollte es praktisch denselben Prozess durchlaufen: nach einem bestehenden Formular suchen, wenn es gültig ist, dann absenden. Submit ruft die POST-Aktionsmethode auf, und wenn Post abgeschlossen ist, wird die Ansicht für die nächste Registerkarte abgerufen. Es funktioniert so 5/10 mal, aber zu anderen Zeiten wird GET vor dem POST ausgeführt, was bewirkt, dass die nächste Seite mit unvollständigen Daten geladen wird. Wenn ich Breakpoints zum Debuggen bringe, sehe ich GET für den nächsten Tab, der vor dem POST des aktuellen Tabs ausgeführt wird.

UI erklärt:

Ich habe eine Benutzeroberfläche mit 4 Navigation <a> Schaltflächen oben - in der Mitte gibt es immer ein Formular - und am unteren Rand habe ich die Schaltflächen Zurück und Weiter.

Formulare werden in MVC mit Ajax.BeginForm

Für jedes Nav Link <a> Element oben habe ich eine JavaScript-Funktion

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);
        });
    }
}

Diese Funktion bindet sich beim Laden der Seite an jeden oberen Link.

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

Meine Next & Previous Buttons lösen grundsätzlich das Click Event aus, dh LoadTabs Funktion.

$('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);
}

Das Problem ist, aus bestimmten Gründen, wenn Nav Link 3 aktiv ist und ich die NEXT-Taste drücke - Anstatt das Formular zuerst über form.submit () zu versenden, wird das Nav 4 ausgelöst - daher läuft GET für nav 4 vor dem form POST von nav 3.

Meine ValidateForm-Methode prüft im Grunde nur, ob das Formular existiert und gültig ist, und dann Submit, andernfalls gibt false zurück. Es ist wie folgt:

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;
}

Meine Spekulation ist, dass form.submit ausgelöst wird, wie es sein sollte, aber da submit ein wenig länger dauert, um es zu beenden, fährt es mit dem nächsten Code-Block in dem Button onclick Ereignis fort.

Ich dachte zuerst, dass dies ein serverseitiges Problem ist, da ich im POST einen großen Datenblock mit ein paar Loops speichere, und jeden Codeblock, der schwer ist, habe ich in diesem Teil

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

WaitAll wird warten und die Ausführung anhalten, bis SomeMethod die Ausführung beendet hat. Ich bin mir nicht sicher, wie ich einen Prozess in JavaScript sperren und auf die Ausführung warten kann. Weil ich denke, wenn ich das form.submit () in ValidateForm irgendwie bis zu seiner fertigen Verarbeitung sperren kann .. über eine Callback-Methode vielleicht ...

Bitte, wenn jemand mich in die richtige Richtung bringen kann, würde ich die Hilfe sehr schätzen. Wenn Sie weitere Informationen benötigen, lassen Sie es mich wissen, ich würde gerne zur Verfügung stellen!





asp.net-mvc-5