0

I am calling workflow from modalpopup on form submit and closed popup after it.

Here is the code on submit button ECS_ProviderSubmit.js:

ECSDalMgr.ECSModule.updateItemRequest(old_data.__metadata.uri, new_data, old_data.__metadata.etag, 'true').then(function(data){
                ECSDalMgr.LoadScripts(listGUID, itemID , REMINDERworkflowSubscriptionID , "");
                Utilities.closeWaitScreenDialogBox();
                Utilities.closeModalPopUp();
        }).fail(function (error) { console.log("Error in getItemById" + error.responseText) });

Here is the code for ECS_DalManager:

this.LoadScripts = function (lstguid, listItemId, subscriptionID, Url) {
    listGUID = lstguid;
    itemID = listItemId;
    workflowSubscriptionID = subscriptionID;
    redirectUrl = Url;
    SP.SOD.executeFunc("sp.js", "SP.ClientContext", function () {
        SP.SOD.registerSod('sp.workflowservices.js', SP.Utilities.Utility.getLayoutsPageUrl('sp.workflowservices.js'));
        SP.SOD.executeFunc('sp.workflowservices.js', "SP.WorkflowServices.WorkflowServicesManager", startWorkflow);
    })
}

function startWorkflow() {
    getWorkflow(listGUID, itemID, workflowSubscriptionID, redirectUrl);
}

function getWorkflow(lstGuid, itemID, workflowSubscriptionID, redirectToUrl) {
var context = SP.ClientContext.get_current();
var web = context.get_web();
var sMgr = new SP.WorkflowServices.WorkflowServicesManager.newObject(context, web);
var subscription = sMgr.getWorkflowSubscriptionService().getSubscription(workflowSubscriptionID);
context.load(subscription);
context.executeQueryAsync(
    function (sender, args) {
        var params = new Object();
        var formData = subscription.get_propertyDefinitions()["FormData"];
        if (formData != null && formData != 'undefined' && formData != "") {
            var assocParams = formData.split(";#");
            for (var i = 0; i < assocParams.length; i++) {
                params[assocParams[i]] = subscription.get_propertyDefinitions()[assocParams[i]];
            }
        }
        if (itemID) {
            sMgr.getWorkflowInstanceService().startWorkflowOnListItem(subscription, itemID, params);
        }
        else {
            sMgr.getWorkflowInstanceService().startWorkflow(subscription, params);
        }
        context.executeQueryAsync(
                function (sender, args) {

                },
                errFunc);
    },
    errFunc);
}

function errFunc(sender, args) {
    alert("Error: unable to start workflow")
    console.log('Error: unable to start workflow' + error.responseText);
}

Now issues is when I call Loadscripts function from ECS_ProviderSubmit.js, it just execute this.LoadScripts function and returns. then after popupmodal get closed and then after startWorkflow() get called. So I get error in context.executeQueryAsync().

It is any way, I can call startworkflow() before closing modalpopup.

  • 1
    Maybe I'm being too simplistic, but shouldn't the workflow be configured to fire on change, then by the mere fact you update the item, the workflow fires, making all the JS code to initiate it unnecessary? – Eric Alexander May 4 '16 at 14:21
0

Now issues is when I call Loadscripts function from ECS_ProviderSubmit.js, it just execute this.LoadScripts function and returns.

Right, because you are doing a lot of async stuff and not waiting for it to be done before moving on to closing the modal.

It looks like you are already using promises in the updateItemRequest function, so I would just continue with that and make the LoadScripts function return a promise as well, and make sure you structure the code so that that promise doesn't get resolved until all of your workflow async calls finish.

Then you could chain your calls more like this:

ECSDalMgr.ECSModule.updateItemRequest([your params]).then(function (data) {
    return ECSDalMgr.LoadScripts(listGUID, itemID, REMINDERworkflowSubscriptionID, "");
}).then(function () {
    Utilities.closeWaitScreenDialogBox();
    Utilities.closeModalPopUp();
}).fail(function (error) { console.log("Error in getItemById" + error.responseText) });

Here's what I was talking about. Notice I made one major structural change by nesting startWorkflow, getWorkflow and errFunc inside LoadScripts so that those functions have access to the dfd deferred object.

this.LoadScripts = function (lstguid, listItemId, subscriptionID, Url) {

    // this is assuming you are working with jQuery and can use jQuery deferreds
    // if you are using some other promise framework then you will have to substitute
    // this with whatever is appropriate for your promise framework
    var dfd = new $.Deferred();

    var listGUID = lstguid;
    var itemID = listItemId;
    var workflowSubscriptionID = subscriptionID;
    var redirectUrl = Url;
    SP.SOD.executeFunc("sp.js", "SP.ClientContext", function () {
        SP.SOD.registerSod('sp.workflowservices.js', SP.Utilities.Utility.getLayoutsPageUrl('sp.workflowservices.js'));
        SP.SOD.executeFunc('sp.workflowservices.js', "SP.WorkflowServices.WorkflowServicesManager", startWorkflow);
    });

    // notice that here I have nested all of your workflow functions *inside* LoadScripts
    // so that they have access to the "dfd" deferred object created at the beginning of the script
    function startWorkflow() {
        getWorkflow(listGUID, itemID, workflowSubscriptionID, redirectUrl);
    }

    function getWorkflow(lstGuid, itemID, workflowSubscriptionID, redirectToUrl) {
        var context = SP.ClientContext.get_current();
        var web = context.get_web();
        var sMgr = new SP.WorkflowServices.WorkflowServicesManager.newObject(context, web);
        var subscription = sMgr.getWorkflowSubscriptionService().getSubscription(workflowSubscriptionID);
        context.load(subscription);
        context.executeQueryAsync(
            function (sender, args) {
                var params = new Object();
                var formData = subscription.get_propertyDefinitions()["FormData"];
                if (formData != null && formData != 'undefined' && formData != "") {
                    var assocParams = formData.split(";#");
                    for (var i = 0; i < assocParams.length; i++) {
                        params[assocParams[i]] = subscription.get_propertyDefinitions()[assocParams[i]];
                    }
                }
                if (itemID) {
                    sMgr.getWorkflowInstanceService().startWorkflowOnListItem(subscription, itemID, params);
                }
                else {
                    sMgr.getWorkflowInstanceService().startWorkflow(subscription, params);
                }
                context.executeQueryAsync(
                    function (sender, args) {
                        // this is the success function that gets called after the workflow is started,
                        // so this is where you want to resolve the "dfd" promise
                        dfd.resolve();
                    },
                    errFunc);
            },
            errFunc);
    }

    function errFunc(sender, args) {
        alert("Error: unable to start workflow")
        console.log('Error: unable to start workflow' + error.responseText);
        // if there was an error, you want to reject the promise
        dfd.reject();
    }

    // this is now the end of the LoadScripts function, so here
    // is where you want to return the "dfd" deferred object's promise
    // to make the calling code wait
    return dfd.promise();
}
  • Nope. It doesn't work. because it goes to Loadscripts method first, after it comes to then, so popup get closed, and after it, it goes to startWorkflow() method – Ubiquitous Developers May 5 '16 at 5:59
  • Yes, but what I'm saying is that you need to change your LoadScripts method to return a promise, and then resolve that promise only after all of the executeQueryAsync calls that have to do with starting the workflow are complete. The then() that's chained after LoadScripts will not pause the code execution unless LoadScripts returns a promise. – Dylan Cristy May 5 '16 at 13:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.