1

I'm having problems waiting for a deferred to complete when using the deferred in the onStepChanging event on the jQuery plugin "jQuery-Steps". This plugin is documented at http://www.jquery-steps.com/. The step returns immediately instead of waiting for the deferred. In my real code I am doing an ajax call and I want to wait for the result before proceeding to the next step.

Here is some sample code:

$(document).ready(function() {
    var form = $("#form1");
    form.children("div").steps({
        headerTag: "h3",
        bodyTag: "section",
        transitionEffect: "slideLeft",
        onStepChanging: function(event, currentIndex, newIndex) {
            $.when(asyncEvent()).then(function(status) {
                return status;
            });
        }
    });
});

function asyncEvent() {
    var dfd = new $.Deferred();

    setTimeout(function() {
        dfd.resolve(true);
    }, 2000);

    return dfd.promise();
}

Any help is greatly appreciated!

Justin Russell
  • 488
  • 2
  • 10
  • Is you ajax too complex to use the [built in async features](http://www.jquery-steps.com/Examples#async)? – prodigitalson Jan 16 '15 at 23:11
  • Can you provide a snippet of the relevant markup? – Zach Wolf Jan 16 '15 at 23:52
  • Is you ajax too complex to use the built in async features? Yes, it is more complicated than just pointing to a URL. Can you provide a snippet of the relevant markup? I'm not sure how much more markup I can provide that would add value. – Justin Russell Jan 19 '15 at 16:31

2 Answers2

2

Your code is expecting an asynchronous function to return synchronously and this will not work. Here is an alternative approach that will disable changing steps until the promise has completed:

$(document).ready(function() {
    var form = $("#form1");
    // initialize the return value as false (since you want to wait for your promise to complete)
    var stepReady = false;
    form.children("div").steps({
        headerTag: "h3",
        bodyTag: "section",
        transitionEffect: "slideLeft",
        onStepChanging: function(event, currentIndex, newIndex) {
            $.when(asyncEvent()).then(function(status) {
                stepReady = status;
            });
            return stepReady;
        }
    });
});

function asyncEvent() {
    var dfd = new $.Deferred();

    setTimeout(function() {
        dfd.resolve(true);
    }, 2000);

    return dfd.promise();
}

It would be better in this instance to use done directly on the returned promise since the purpose of then is to manipulate the state. So, it would change to:

onStepChanging: function(event, currentIndex, newIndex) {
    asyncEvent().done(function(status) {
        stepReady = status;
    });
    return stepReady;
}
Rob M.
  • 35,491
  • 6
  • 51
  • 50
0

The step run immediately without waiting for your deferred because $.when is run asynchronously and in your script you are return status for $.when callback not for onStepChanging.

My suggestion, yo need to return false your onStepChanging event by default, and do step change manually..

may be something like this

onStepChanging: function(event, currentIndex, newIndex) {
    $.when(asyncEvent()).then(function(status) {
        if(status)
        {
            if (currentIndex < newIndex)
            {
                form.children("div").steps('next');
            }
            else
            {
                form.children("div").steps('previous');
            }
        }
    });

    return false;
}

Sorry if I write some mistake, I'm not testing this code well, I just read example on http://www.jquery-steps.com/Examples and try to understand how it work, but the main idea is just return false by default and do step change manually.. Hope it help..

Park Dong Gun
  • 114
  • 1
  • 4
  • This is a good suggestion. I gave it a shot and there are two issues. First, when false is returned a CSS class called "error" is added to the navigation link. This is easily overcome by editing the "error" CSS class. The second issue I could not overcome - it runs the "onStepChanging" event even when changing steps though the "next" method. This causes an endless loop. – Justin Russell Jan 19 '15 at 16:35