James Wilson
James Wilson

Reputation: 809

How to order this jQuery tha runs ajax then must return true

I have a very simple javascript for form validation that checks my form fields. the function either builds up an errorList variable and returns false, of if the variable is empty the function returns true and submits.

I have added a new layer to this validation function. I now want to call an external function that simply sends an Ajax request with all the form validation and in turn that emails me to say if a user passed the form validation or did not.

Calling this external function is fine when the form does not validate, as when I return false; obviously the form does not submit, thus allowing the ajax to finish.

I just cannot figure out how to fire the external function, let it finish, then return true and let the form submit. It just skips past the ajax request.

Can some one please help with the logic?

Validation function:

if (errorList.length > 0) {

    // Log the errors in quote.shared.js:
    logValidationErrors("N/A - Pre Quote", $("#prequote-form"), "productname", errorList);

    $("#error-list").html("");
    $("#error-list").append(errorList);
    $("#error-div").slideDown(500, function() {
        $( '#error-div' ).ScrollTo(300);
    });
    return false;
} else {

    // Log the valid passing through this function in quote.shared.js:
    logValidationErrors("N/A - Pre Quote", $("#prequote-form"), "productname", "none"); 
    return true;
}

The ajax function:

// logValidationErrors
function logValidationErrors(xOrderNumber, xForm, xProduct, xErrors) {
    /*
    alert(xOrderNumber);
    alert(xForm);
    alert(xProduct);
    alert(xErrors);
    */

    $.ajax({
        url:    "log-clientside-events.php?" +
                "type=javascript-errors&" +
                "ordernumber=" + xOrderNumber + "&" +
                "formvalues=" + encodeURIComponent(xForm.serialize()) + "&" +
                "product=" + xProduct + "&" +
                "errors=" +  encodeURIComponent(xErrors),
        context: document.body,
        cache: false,
        timeout: 10000,
        success: function(sHTML){

        },
        error:function (xhr, ajaxOptions, thrownError){
            //window.location.href = window.location.href;
        }
    });


}

Anup helped with the solution. The key is to create a "flag" variable that is false the first time the Ajax runs, then it's set to true when the ajax completes, then the form is submitted again, then the "flag" check skips the Ajax stage second time round - and returns true.

if (errorList.length > 0) {

    // Log the errors in quote.shared.js:
    logValidationErrors("N/A - Customer Details", $("#customer-form"), "productname", errorList);

    $("#error-list").html("");
    $("#error-list").append(errorList);
    $("#customer-login-success-message").slideUp(100);
    $("#error-div").slideDown(500, function() {
        $( '#error-div' ).ScrollTo(300);
    });
} else {

    if (validationSuccessfullyLoggged) {
        return true;

    } else {
        // Log the valid passing through this function in quote.shared.js:
        logValidationErrors("N/A -  Customer Details", $("#customer-form"), "productname", "none"); 

    }
}

return false;

Function that deals with the ajax:

// logValidationErrors
var validationSuccessfullyLoggged = false;

function logValidationErrors(xOrderNumber, xForm, xProduct, xErrors) {
    /*
    alert(xOrderNumber);
    alert(xForm);
    alert(xProduct);
    alert(xErrors);
    */

    if (xErrors == "none") {
        xErrors = "<li>Form Validated Successfully</li>";   

        submitForm = true;
    } else { 
        submitForm = false;
    }

    $.ajax({
        url:    "log-clientside-events.php?" +
                "type=javascript-errors&" +
                "ordernumber=" + xOrderNumber + "&" +
                "formvalues=" + encodeURIComponent(xForm.serialize()) + "&" +
                "product=" + xProduct + "&" +
                "errors=" +  encodeURIComponent(xErrors),
        context: document.body,
        cache: false,
        timeout: 10000,
        success: function(sHTML){

            //alert(validationSuccessfullyLoggged);

            if (submitForm) { 
                validationSuccessfullyLoggged = true;
                xForm.submit();
            }
        },
        error:function (xhr, ajaxOptions, thrownError){
            //window.location.href = window.location.href;
        }
    });


}

Upvotes: 1

Views: 100

Answers (2)

Skecci Dev
Skecci Dev

Reputation: 121

logValidationErrors("N/A - Pre Quote", $("#prequote-form"), "productname", "none");
return true;

Remove the "return true;" from the above code and when you need to return somthing from an ajax usually you must do in inside SUCCESS function ... so

success: function(data)
{ 
    doSomething;
    return true; 
}

Upvotes: 0

Anup
Anup

Reputation: 106

The general cause of your problem is that when you make the AJAX request, it is asynchronous (the first 'a' in AJAX). Hence, after you have called your logValidationErrors function, the return true is running before the ajax operation returns.

To address this, there are 2 general approaches I can think of (though there may be others I've not thought of):

1) In jQuery's ajax method you could set async to false (so it is not asynchronous anymore). See their docs for the details: http://api.jquery.com/jQuery.ajax/

I would personally not recommend this unless it is under really exceptional circumstances (and I don't think your example would qualify, for me), as you lock the browser for a while, and defeat the purpose of asynchronous requests.

2) One alternative is you would always return false from your main JavaScript code. In other words, after calling the logValidationErrors function, return false as well (or just have one return false statement after your if/else block. Then, when the ajax operation has actually completed, in the success handler you want to trigger your success scenario (e.g. submit the form), and in the error scenario (see the error option in the jQuery ajax documentation), you would want to invoke your error scenario.

Without seeing more of your code and when you are invoking your particular if/else sample you posted, I can't be more precise and it may be that there are more elegant ways of handling this. And there may be other considerations to bear in mind too depending on what actions you want to do. For example, if submitting your form is just going to call this same if/else block, you may need a tracking variable to indicate that you have already made the initial ajax request so that this time you can go ahead and submit if needed.

Hope that helps.

Upvotes: 3

Related Questions