11.01.2010: Updated code due to a bug (line 36 is updated). Thanks to Scott Muldowney for spotting it.
The scenario:
You open a list item in EditForm, and the list item has a running (not yet completed) workflow. Nothing prevents you from editing the item, but when you try to save your edited item:
Save Conflict
Your changes conflict with those made concurrently by another user. If you want your changes to be applied, click Back in your Web browser, refresh the page, and resubmit your changes.
In this article i will provide a solution for:
- Checking the workflow status, and if not finished, set a timer that checks the workflow every 5 seconds for a set period of time.
- Refresh the page if the workflow finishes within the maximum wait time.
If status is “In progress”, the timer runs, and the status is checked every 5 seconds:
If timed out, you get this:
This article is a follow-up on Prevent editing of a list item if the workflow has failed. You have to read that article before continuing with this one.
As always we start like this:
Create a document library to hold your scripts (or a folder on the root created in SharePoint Designer). In this example i have made a document library with a relative URL of “/test/English/Javascript” (a sub site named “test” with a sub site named “English” with a document library named “Javascript”):
The jQuery-library is found here. The pictures and the sourcecode refers to jquery-1.3.2.min. If you download another version, be sure to update the script reference in the sourcecode.
The scripts “interaction.js” and stringBuffer.js” is created by Erucy and published on codeplex – you find them here.
Add a CEWP below your EditForm, and add this code:
<div id="customTimerMsg"></div> <div id="customTimer"></div> <div id="customTimerCheck"></div> <script type="text/javascript" src="/test/English/Javascript/jquery-1.3.2.min.js"></script> <script type="text/javascript" src="/test/English/Javascript/interaction.js"></script> <script type="text/javascript" src="/test/English/Javascript/stringBuffer.js"></script> <script type="text/javascript" src="/test/English/Javascript/RefreshWhenWorkflowCompletes.js"></script> <script type="text/javascript"> // How long will the timer run before aborting maxWaitSec = 20; // Change ListGuid and Workflow "FieldInternalName" listNameOrGuid = 'A3749468-0C23-493B-8854-06DF04200B43'; workFlowInternalName = 'MyWF'; administratorEmail = 'alexander.bautz@gmail.com'; </script>
Parameters explained:
- maxWaitSec: The max wait time in seconds
- listNameOrGuid: Display name or Guid of current list
- workFlowInternalName: The “FieldInternalName” of the workflow to check
- administratorEmail: The administrator’s email – for when the workflow has failed
The code for the file “RefreshWhenWorkflowCompletes.js” is found here:
/* Refresh list item when workflow finishes * --------------------------------------------- * Created by Alexander Bautz * alexander.bautz@gmail.com * https://spjsblog.com * v1.0 * LastMod: 10.01.2010 * --------------------------------------------- * Include reference to: * jquery - http://jquery.com * interaction.js - http://spjslib.codeplex.com/ * stringBuffer.js - http://spjslib.codeplex.com/ * --------------------------------------------- * Call from a CEWP below the list form in EditForm */ $(document).ready(function(){ checkStatusAndRefresh(); }); var SiteTitle = $.trim($(".ms-sitetitle a").text()); var ListName = $.trim($(".ms-pagetitle a").text()); function checkStatusAndRefresh(){ var wfStatus = getWorkflowStatus(); if(wfStatus==3){ // 3 = "Error Occured" $("#part1").hide(); // Hide the list form $("#part1").before("<div class='ms-sitetitle'>A workflow has failed. You cannot edit this item until this issue is resolved.</div>" + "<div style='padding-left:10px'><a title='Click to send e-mail to an administrator' href='mailto:" + administratorEmail + "?subject=Failed workflow on site: " + SiteTitle + ", list: " + ListName + ", itemId: " + getID() + "'>Click to send e-mail to an administrator</a></div>"); }else if(wfStatus==2){ $("#part1").hide(); // Hide the list form waitingForRefresh = true; customTimer(); }else{ if(typeof(waitingForRefresh)!='undefined' && waitingForRefresh){ refreshPage(); } } } function customTimer(s){ if(typeof(s)=='undefined')seconds = 0; if(typeof(accumulated)=='undefined')accumulated = 0; if(accumulated<maxWaitSec){ if(seconds<5){ seconds+=1 $("#customTimerMsg").html("<div class='ms-sitetitle'>The workflow has not yet finished: Waiting for a maximun of " + maxWaitSec + " seconds,<br>checking the workflow every 5 seconds.</div>"); $("#customTimer").html("<div style='padding-left:10px'>Waiting: " + (accumulated + seconds) + "</div>"); setTimeout(function(){ customTimer(seconds); },1000); }else{ accumulated = accumulated + seconds; $("#customTimerCheck").html("<div style='padding:10px;color:red'>Checking WF...</div>").show().fadeOut(1750); checkStatusAndRefresh(); } }else{ $("#customTimerMsg").html("<div class='ms-sitetitle'>The workflow did not finish during the time specified.</div>" + "<div style='padding:10px;font-size:12px'><a href='" + L_Menu_BaseUrl + "'>Return to site "" + SiteTitle + ""</a>&nbsp;|&nbsp;" + "<a href='javascript:refreshPage();'>Wait for " + maxWaitSec + " new seconds.</a></div>"); $("#customTimer").html(''); } } function refreshPage(){ window.location.reload(); } function getWorkflowStatus(){ var thisID = getID(); wsBaseUrl = L_Menu_BaseUrl + '/_vti_bin/'; var item = getItemById(listNameOrGuid,thisID,[workFlowInternalName]); if(item != null){ return item[workFlowInternalName]; } } function getID() { var ID = ''; var end = window.location.search.indexOf('&'); if(window.location.search.indexOf('&')<0){ ID = window.location.search.substring(4); }else{ ID = window.location.search.substring(4,end); } return ID; }
Save as “RefreshWhenWorkflowCompletes.js”, and upload to your scriptlibrary as shown above.
Ask if anything is unclear.
Regards
Alexander
Worked great. I appreciate the help on this, its going to help me on several projetcs.
ANy chance you have anything nifty to delete or move dublicate items in a list? I need to keep the newest item, but move the older ones to another list for review, then to be deleted.
I’m not sure if this is relevant, but have you seen this post about assuring only unique items being added to a list:
SharePoint list’s or document library’s: Primary key in selected field
If this not what you want, the code gives you an example of how to query a list and check for duplicates.
Come back to me if you have any more questions.
Alexander
I am getting an error on one particular list and was wondering if you had this come up during your testing.
Error:’waitingForRefresh’ is undefined
Code:0
Any ideas?
A bug.. Fixed it (line 36 in the code) – thanks for spotting it.
Alexander
One last question.
function getWorkflowStatus(){
var thisID = getID();
wsBaseUrl = L_Menu_BaseUrl + ‘/_vti_bin/’;
var item = getItemById(listNameOrGuid,thisID,[workFlowInternalName]);
if(item != null){
return item[workFlowInternalName];
In the above code do I need to replace with my GUID and WorkFlow name or are these just references?
Hi,
These variables are passed from the code in the CEWP. No need to edit anything in the file “RefreshWhenWorkflowCompletes.js”.
Alexander
Hi Alexander,
Thanks for all of your great tips.
I would like to use the functionality above in conjunction with “Redirect from NewForm to EditForm or custom page”.
What I would like to do is wait until a workflow completes before redirecting from the NewForm to the EditForm.
How would I achieve this?
Kind Regards,
Sam
Hi,
If you want to redirect to EditForm from NewForm, the item (and workflow) is not created until you save it. You will have to put this code in EditForm and execute it after the “redirect-script” has finished redirecting you to the correct item.
Alexander
appreciate this is some years old, but is something am looking for, so was wondering if the scripts, especially “interaction.js” and stringBuffer.js” work in SP2010?
other question is where you say “Add a CEWP below your EditForm” does that mean at the bottom of editform.aspx or…?
sorry for the “beginners” questions….!
Alexander,
Great stuff! I use several of your add-ins (licensed) on the job.
Can this “Prevent edit until workflow is complete” still be used with SharePoint 2013 and the latest version of DFFS add-in? If so, do you still put the CEWP below the edit form, OR do you include the function code in the JS page on the DFFS backend?
Thanks!
Syz
Sorry, but this is almost 5 years old and will not work in newer versions of SharePoint without a rewrite.
I currently have a lot on the schedule, but if you want to try to modify it, you must look at SPJS-utilty.js for the helper functions like “getItemById” and get rid of “stringbuffer” and “interactions” as these are outdated.
Alexander