1

I recently posted about an issue I had, in which I wanted to run a workflow only when a specific column changes. I did not get a lot of answers, but in short, I found out that there does not seem to be any Sharepoint Designer way of doing this.

I brainstormed a bit and began wondering, whether what I want to do can be done in Javascript. Say I load the value of the column in local storage on page load and compare the value in local storage to the value of the column when the save button is clicked. If this condition is met, i.e. column on page load != column on save, retrieve the list id from the query string and fire the workflow using SP.WorkflowServices.

My issue is that the EditForm, on save button clicked, seems to be redirecting back to the Document Library quickly, before the workflow starting code is actually being hit. I also tried to use a Jquery deferred object to try make sure that the flow of the code does not continue before the startWorkflow method is finished. The code works in this case, but only when debugging, which means that when no breakpoints are hit and the code flow is left to run on its own, the page would have redirected before the logic would have been done.

I am working in a Sharepoint Online environment. Below is the code:

https://gist.github.com/anonymous/0d01db91dbb293f3940a4825e264d2a8

Any suggestions? What is wrong with my code? Or is there another way that actually works?

3

When I have had to wait for an async operation to complete that should happen between when the user clicks Save and when the form is actually submitted, I used the PreSaveAction function to kick off the async operation and prevent the form from submitting until I am ready.

PreSaveAction is called when the user clicks Save. If you return false from PreSaveAction, the form will not submit, and if you return true, it will.

So the basic logic flow goes kinda like this:

  • On page load, set a globally accessible flag to false
  • In PreSaveAction, check the flag, if it's false, kick off the async operation and return false from PreSaveAction to prevent the form submitting
  • In the async success callback, set the flag to true, and then re-fire the click event on the save button (through code) to re-submit the form
  • In the PreSaveAction, check the flag, it will be true (async operation has finished), so return true to allow the form to submit

Here's an example of how I would set it up. It's a little pseudo-codey because I haven't put in the real selectors to get at the field in question or the Save button, and I kind of glossed over the fact that you are actually making two async calls, one to get the workflow subscription, and then one to actually start the workflow, so the "success" function below is really meant to be the second success callback after the workflow really starts:

// set up a namespace
var DEC = DEC || {};

// set our flag
DEC.ProceedToSave = false;

// set the placeholder to store the original field value
DEC.OriginalFieldValue = '';

// set up PreSaveAction (it should be defined in the global namespace)
function PreSaveAction() {

    // check the flag to see if we can submit the form
    if (DEC.ProceedToSave){
        return true;
    }

    // check to see if the field value changed
    var fieldValue = $('selector for field').val();
    if (fieldValue === DEC.OriginalFieldValue) {
        // it's the same so no action requred, go ahead and submit the form
        return true;
    }

    // if we made it this far, we must have to start the workflow
    DEC.StartWorkflow();

    // don't submit the form, we need to wait for the async call
    return false;
};

$(document).ready(function() {
    // store the initial field value
    DEC.OriginalFieldValue = $('selector for field').val();
});

DEC.StartWorkflow = function startWorkflow() {

    //
    // do all the stuff you need to start the workflow
    // here, like getting the item ID from the query string,
    // creating the context and query, etc.
    //

    context.executeQueryAsync(successCallback, failCallBack);

    function successCallback() {
        // workflow has started!
        DEC.ProceedToSave = true;
        // "click" the save button again to resubmit the form
        $('selector for Save button').click();
    }

    function failCallBack() {
        // do your failure behavior
    }
};
  • +1 PreSaveAction, and then its classic en.wikipedia.org/wiki/Semaphore_(programming) – Danny '365CSI' Engelman Mar 24 '17 at 17:26
  • Your method is brilliant and it seems to achieve what I want! Also thank you for taking the time to post the pseudo-code. I had already done something similar but I particularly liked your implementation of the global variable via the namespace. My only issue now is that when I am starting the workflow on the item and then submitting the edit a bit after, the list item would already have changed version. This returns the error: "Sorry something went wrong, The file has been modified by...". I will have to come up with something to go around that! :) – Jurgen Cuschieri Mar 24 '17 at 21:37
0

You can check for an individual changed field in a Designer workflow, unless it's something like a multiline text field - those get more complicated. If the field doesn't change, the workflow will still run but it won't do anything.

You do have to add a new field to the list/library. Example: send an email when a status field changes.

Add a field, like "LastStatus". You can hide it from the forms since it will only be used in workflow.

Test to see if the current column is equal to that new field, do your logic, then set the hidden field equal to the main field. That will keep the logic from running until that specific field changes again.

enter image description here

  • Thank you but the method I was seeking would specifically not require an unneccessary workflow being run. Even though the logic would not be done in such instance, the workflow would still need to be hit to check the condition. Your solution is exactly my current solution but since I needed it for many different content types, I did not want to overflow the system with unnecessary workflows! Thanks again though! – Jurgen Cuschieri Mar 24 '17 at 21:40
0

I am jumping back to your first statement "Unable to trigger workflow when a field changes". I was able to accomplish this case by following below steps. See your case will helpful which is a completely OOB solution.

  • Add a hidden field to a list item to store your field value which you want to trigger.
  • write a workflow on item change.
  • Compare your field value with hidden field value. If both are different execute logic and copy field value to hidden field value.

If I can get your business case will assist better way as I had worked these field changes in different cases without hidden field also.

Thanks, Venkat Konjeti

  • Thanks for taking the time to post an answer. However, I was looking for a solution, where the workflow would only be initiated on the change of a column. Your solution seems to require access into the workflow, and the logic would be fired if a condition is met. This is not ideal in my scenario as I do not want to add more workflows to the system but rather decrease them. Thanks again for your time! – Jurgen Cuschieri Mar 24 '17 at 21:43

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.