Stop event from continuing on deferred.reject

2019-06-14 12:26发布

问题:

Hoping some of you may help me with this problem.

I have a few navigation link on top of my application which have active and not-active state. In theory, I want to jump from one to another and if there exists a form which isn't complete/valid, I trigger validation errors and stay on the same page. What is happening in my case is form validation works fine but navigation links on top change state from non-active to active, whichever was clicked.

I have a ValidateForm function that validates and submits the form if its is valid, else it returns deferred.reject();

function ValidateForm(submitAnyway) {
    var deferred = $.Deferred();
    var form = $('form');

    // if form doesn't exist on the page - quit
    if (typeof form[0] === "undefined") return true;       


    // now check for any validation errors
    if (submitAnyway) {
        if (!$(form).valid()) {                
            deferred.reject();
        } else {
            $(form).submit();
            deferred.resolve();
        }
    } else {
        deferred.resolve();
    }

    return deferred.promise();
}

I have a click event for those top navigation links as below:

var DonutsClickEvent = function (e, arg) {
    var url = $(this).attr('data');
    var data = { param: arg };

    if (typeof url === "undefined") return false;

    $.when(window.ValidateForm(false)).then(
        function () {
            LoadPartialView_Main(url, data);                
        },
        function(){
            return false; // I'm trying to return false here to stop event from continuing 
        }
    );  
    Console.log("This statement runs before $.when completes");
    // and event continues and the clicked nav button changes 
    // its state from non-active to active, even though form doesn't validate
}

I recently added $.Deferred functionality to my code due to some events firing with messed up sequence... Before my validateForm method would return true or false and based on that i'd continue executing event if true, if false i'd stop and it was all good.

Not sure what am I doing wrong here. I'd appreciate any kinda help.

Thanks!

Johny

回答1:

You can't asynchronously decide whether you want to block the default action or not. By the time you get your async result, your function has already returned and the default action has already occurred.

If you have to validate asynchronously, then you will have to always block the default action. If the validation succeeds, then you will have to manually carry out the desired action with Javascript.

So, assuming that LoadPartialView_Main() is what you want to have happen when validation succeeds, you can do something like this:

var DonutsClickEvent = function (e, arg) {
    var url = $(this).attr('data');
    var data = { param: arg };

    if (typeof url === "undefined") return false;

    window.ValidateForm(false).then(function () {
        LoadPartialView_Main(url, data);
    }, function(err){
        // probably show validation error message to the user here
    });  
    // always prevent default action
    return false;
}

Also, there's no reason to use $.when() with a single promise. You can just use window.ValidateForm(...).then(...).