1,804 articles and 15,097 comments as of Saturday, June 4th, 2011

EndUserSharePoint has combined resources with NothingButSharePoint.com. You can now find End User (Mark Miller), Developer (Jeremy Thake) and IT Pro SharePoint content all in one place!

This site is a historical archive and is no longer being updated. Please update your favorites, bookmarks and RSS feeds.

NothingButSharePoint.com
Wednesday, April 21, 2010

4 Clicks or 1? Using jQuery to Start a SharePoint Workflow

Guest Author: Jason MacKenzie
Intelligence Among Us

The IT Urgent Change process needs to be automated.  It’s relatively simple and after gathering the requirements its clear that this can be accomplished using SharePoint and a SharePoint Designer workflow.  The workflow is created and published to the list.  The decision is made that the workflow will be started manually as opposed to automatically when the Change Request is created.  Everyone in IT has contribute access to the list and there are no security requirements related to who can or can’t start a workflow.

This means a user must take the following steps to initiate the workflow:

  1. Click the context menu and click the Workflows menu item

  2. Select the Change Process Workflow.

  3. Initiate the Workflow

That’s a few more clicks than should be required so I wanted to find a way to make starting a workflow a one-click affair.  I knew this should be relatively simple with jQuery and the Dataview Web Part so I’d like to detail how I accomplished this so others can hopefully benefit from it.

The end result looks like this:


When the user clicks the Start Workflow link they see a nice Ajax loading image as seen below


When the workflow has been initiated they are presented with a confirmation message telling them the process is underway


On to the solution!  First I need to give a shout out to Marc Anderson , the creator of the jQuery Library for SharePoint Web Services which can be found here: http://spservices.codeplex.com/.  This is such a handy tool for interacting with the SharePoint web services from the client and this was my first opportunity to use it.  I simply downloaded the JS files and put them in my SharePoint Scripting Resource Centre site collection as first conceived by Mark Miller at EndUserSharePoint.com.  The original post can be found here: http://www.endusersharepoint.com/2010/01/05/build-a-sharepoint-scripting-resource-center/

Once that was done I need to do a few things.  I created a Web Part Page and opened SharePoint Designer.  I then added the Change Request list to one of the web part zones.  In order to get the customizations that wanted needed to create a DataView out of it so I simply right clicked on the list and converted it to a XSLT Dataview.   That’s all I really need to do here so I saved the page and opened it up in the browser.  What you can do with a dataview is almost limitless.  The best way to tackle customizations is to make all the changes you can using the SPD interface.  Once you have reached the limits of what you can do there you can start customizing the XSL.  Refer to the following series by Marc to learn everything you need to know about XSL and the DVWP.  http://www.endusersharepoint.com/2010/01/19/unlocking-the-mysteries-of-data-view-web-part-xsl-tags-part-1-overview/

When you modify a dataview in the browser you have a different set of options then when you work with a regular list.  The important thing we want to do here is modify the XSL in order to achieve the look and functionality we want.


In the interests of saving my sanity I copied the XSL and pasted it into SharePoint Designer (just a new XML document) so I could at least have the benefit of some colour in my life.  I added the following snippet  which I’ll explain as I go.

<xsl:if test=”not(normalize-space(@ChangePr) = ‘5′ or normalize-space(@ChangePr) = ‘2′)”>

<div>

<xsl:attribute name=”id”>

<xsl:text>WorkflowDiv</xsl:text>

<xsl:value-of select=”@ID” disable-output-escaping=”yes”/>

</xsl:attribute>

<a href=”#”>

<xsl:attribute name=”onclick”>

<xsl:text>javascript:StartWorkflow(‘</xsl:text>

<xsl:value-of select=”@EncodedAbsUrl” disable-output-escaping=”yes”/>

<xsl:text>’,'</xsl:text>

<xsl:value-of select=”@ID” disable-output-escaping=”yes”/>

<xsl:text>’);</xsl:text>

</xsl:attribute>

Start Workflow</a>

<img style=”visibility:hidden” src=”http://employeeportal/sites/sprc/PublishingImages/ajax-loader.gif”>

<xsl:attribute name=”id”>

<xsl:text>Loader</xsl:text>

<xsl:value-of select=”@ID” disable-output-escaping=”yes”/>

</xsl:attribute>

</img></div>

</xsl:if>

The result I want to achieve with this is another column in the dataview with the “Start Workflow” link that will call a Javascript function and passes in a few parameters and uses the jQuery Library for SP Web Services to kick off the workflow.

The following section says that we’re only going to render the link when the workflow is not complete or cancelled.  When you covert a list view to a dataview your workflow column which normally reads “In Progress’, “Completed” etc. switches to the numerical value.  Why?  I haven’t a clue.  But the easiest way is to use SPD to create some conditional formatting and then just copy the XSL that is generated.

<xsl:if test=”not(normalize-space(@ChangePr) = ‘5′ or normalize-space(@ChangePr) = ‘2′)”>

You can see that the 2 values we pass to our StartWorkflow function are the EncodedAbsUrl and the ID of the list item in question.  The EncodedAbsUrl for a list item looks like this: http://servername/sites/its/Lists/Change%20Request/107_.000.   We also output a hidden image with our nice loading image downloaded from http://www.ajaxload.info that will appear beside each item while the workflow is initiating.

Also note that our loading image and the div that wraps everything have an id property that concatenates on the list item id to it that we’ll use in our client side script.

On to the jQuery.   We need to add a Content Editor Web Part to our page and place the following script inside:

Our jQuery and jQuery Web Services references

<script type=”text/javascript” src=”/sites//sprc/Resources%20%20jQuery/jquery-1.3.2.min.js”></script>

<script type=”text/javascript” src=” /sites/sprc/Resources%20%20jQuery/jQuery%20SP%20Services/jquery.SPServices-0.5.4.min.js”></script>

<script type=”text/javascript”>

function StartWorkflow(ItemURL, ItemID)

{

var loadingImage = ‘Loader’ + ItemID

var workflowDiv = ‘WorkflowDiv’ + ItemID

//Show our loading image

document.getElementById(loadingImage).style.visibility = ‘visible’;

$().SPServices({

operation: “StartWorkflow”,

item: ItemURL,

templateId: “{04ee1c93-f6b7-49b3-a79c-fa3142ecd688}”,

workflowParameters: “<root />”,

completefunc: function() {

document.getElementById(workflowDiv).innerHTML = ‘Workflow Started’;

}

});

}

</script>

As you can see there is very little scripting required here.  We take the URL of the list item and the item id.  We then show the loading image and make the web service call through Marc’s library:

There are 4 parameters.

  1. The operation is “Start Workflow”
  2. The URL is the value of the EncodedAbsUrl for the list item mentioned earlier.

The template id is the guid of the workflow template that we created in SharePoint Designer.  You can find this out by following the first 2 steps at the very beginning of this article and then copying the URL from your browser.  It will look something like this:

http://servername/sites/its/Workflows/Change%20Process/Change%20Proce.aspx?List=d0fa2d98-6086-4c97-be85-4746c801e7f3&ID=89&TemplateID={04ee1c93-f6b7-49b3-a79c-fa3142ecd688}&Source=http%3A%2F%2Femployeeportal%2Fsites%2Fits%2FLists%2FChange%2520Request%2FAllItems%2Easpx

You can see that there is a TemplateID value in the query string and that’s what we want

  1. Our workflow doesn’t have an initiation screen so we simply pass it an XML node.  You have to do this or the workflow will throw an exception.  This took some digging to find out why the workflow wouldn’t start.
  2. completefunc – what we want to happen when we’re done.  In this case we just want to get rid of the image and let the user know the workflow started.  Remember that AJAX is asynchronous so if you try to take post-initiation actions with code inline it will actually run prior to the workflow having been started.  If you want something to happen after the call to the SPServices library is done, put it in the completefunc.

There is no error handling in this solution yet but if you go to Marc’s Codeplex site you can see methods on how you can have error information returned and then trap them. It’s pretty straightforward.

That is how I used, jQuery, the jQuery Library for SharePoint Web Services and the DataView Web Part to allow a workflow to be started with one click.

Guest Author: Jason MacKenzie
Intelligence Among Us

Jason has been an IT professional for 12 years and has worked in a variety of roles from software development to managing business solutions for a large international automotive supplier. He has developed mission critical software solutions for the manufacturing industry and has experience in the government and educational fields as well.

Jason is a social networking enthusiast and is currently working as an independent SharePoint architect. Jason helps organizations with strategy and implementation guidance related to  architecture, governance, processes as well as hand-holding and facilitating a good group cry every now and again. Jason’s goal is to actively participate in the community and share what he has learned in order to help people and business leverage their investment in this critical platform.

 

Please Join the Discussion

28 Responses to “4 Clicks or 1? Using jQuery to Start a SharePoint Workflow”
  1. Jason:

    Great article! (Hopefully this one won’t incur the Wrath of Jay.)

    Thanks for the shout outs, and I’m really glad to see you doing this with SPServices.

    I’m curious why you don’t edit your DVWP’s XSL in SharePoint Designer directly. Once you’ve converted the LVWP to XSLT (ending up with a DVWP), you’ve got everything right there in SPD. Why switch to the browser for your edits, especially when it sounds like you just turned around and pasted the XSL back into SPD to edit it?

    Really nice find on the

    workflowParameters: “<root />”

    option, too.

    M.

    • Rebecca says:

      Can you elaborate a little on the workflowParameters: “” line? While the code is not throwing any errors, that is the only line that seems a little ambiguous and the workflow isn’t running. Thanks!

      PS – Also a huge fan of spServices and never use the browser for XSL unless I can’t get around it (don’t think that has happened yet).

  2. Hey Marc,

    I did do that for most of it. The only thing that tripped me on was formatting the link to kick off the workflow. So I created the column and applied the conditional formatting and then did the rest in the browser. I only pasted it back into SPD (in an XML file) so I could read it more easily while working. I’d be curious to know if I could have done the whole thing in SPD.

    Thanks again for the SPServices library. It’s a fantastic tool.

    Jay

    • Yes, I would have edited the whole time in SPD. I work almost exclusively in the Split View so that I can take advantage of the Common Dialogs, where possible, and otherwise write directly in the XSL and see the results below. (You have to click in the lower pane to see your changes “take”.)

      I wouldn’t wish that big white edit box which is available through the UI for DVWPs on anyone!

      M.

  3. eric says:

    Great article. I had looked into firing manually triggered workflows via a hyperlink before and hit a roadblock. No matter what I had tried, it wouldn’t fire. Next time that situation arises, I’ll definately be looking at implementing this.

  4. Jason – Get a gravatar! I want to know who to fire darts at. Same for you Eric… — Mark

  5. Ok – Done! Let’s see if it works.

    • Seems to be working fine… if you’re in a windowless room, at midnight, with the lights off.

      Interesting hickup. In the admin area of WordPress, the Gravatar is showing up fine, showing you with a full head of hair. Here, it’s showing solid black unless it’s a caching issue. I’ll check back in an hour.

  6. This is where I found the “” trick. I wanted to make sure I gave props to everyone that helped me.

    http://www.moss2007.be/blogs/vandest/archive/2008/01/18/programmatically-start-workflow.aspx

  7. Chris Quick says:

    I’m curious, since you have jQuery already available, why are you using:

    document.getElementById(loadingImage).style.visibility = ‘visible’

    instead of

    $(loadingImage).show()

    You just need to make sure the ‘#’ sign is at the beginning of the loadingImage variable (i.e. var loadingImage = ‘#Loader’ + ItemID)

    Also, you can use a similar shortcut for the text in your div:

    var workflowDiv = ‘#WorkflowDiv’ + ItemID;
    $(workflowDiv).html(”Workflow Started”);

    Love the idea, but I always cringe when I see getElementByID… sorry :)

  8. Rebecca says:

    Sorry for posting again, but no one answered my question :)

    Can you elaborate a little on the workflowParameters: “root” line? While the code is not throwing any errors, that is the only line that seems a little ambiguous and the workflow isn’t running. Thanks!

  9. David says:

    Hi Jason
    Wow, what a cool bit of code. Have got it working on a new dashboard and learnt huge amount about XSL between this and Marc articles. Now have it working with graphic images and going to expand that out.

    One little gotcha I found (not in your code). I modified the workflow for testing to only email me, and found that the template ID changed, which makes sense as its a new workflow. Just means a quick update to the call, but worth letting every know!

  10. David,

    I’m glad this helped you out and wanted to know your comment helped me out as well. I published a new version of the workflow and was trying to understand why the call wasn’t working any more :)

    Thanks!

  11. prabhakaran says:

    how to send the parameters in workflow and use that parameter to send mail in spd workflow.

    workflowParameters: “asdasdas”,

    gives error

  12. Rajdeep says:

    Hi,

    Can you please tell me where you added the the below code in the DVWB ?

    WorkflowDiv

    javascript:StartWorkflow(‘

    ’,’

    ’);

    Start Workflow

    Loader

    Whenever I am trying to add the same its throwing error and the webpart is not displaying. I am new to it. Please reply.

    Thanks.

  13. Courtney Dulany says:

    I really appreciated this article, the fact that it took so many clicks to run a workflow is actually kind of embarrasing when your client wants as few clicks in the process as possible.

    I did run into a little bit of troubl with EncodedAbsUrl not providing any value. I ended up replacing:

    javascript:StartWorkflow(‘

    ’,’

    ’);

    With the following:

    javascript:StartWorkflow(encodeURI('

    http://ccesc2.gdit.com

    '),'

    ');

    I know it may not be pretty, but I have a deadline to meet and this was a life saver. Thanks Jason and Mark!

  14. Rajdeep says:

    Hi,

    Really Nice Post!
    I got answer of my last post. But I have one more :)
    I am able to start the workflow on click. But now my requirement is to capture the user who clicked on the button to start the workflow and update a column in the list with the captured name.

    Can anyone help on this ?

  15. Deepak Seth says:

    Hi Jason, Very nice article.

    We followed your steps exactly and mostly it works. However, we are running into an issue where @EncodedAbsUrl has null value for all rows. Any suggestions what may be wrong or what I could try to debug it. BTW, @ID returns proper value of row id.

    Thanks in advance,

    Best Regards,
    Deepak

    • Puja says:

      Hi Deepak,

      We are also facing the same issue. Are you able to find solutions.

      Regards,
      Puja

      • Great article, exactly what SP is missing!
        I Had trouble with this myself.
        Only Document Libs have EncodedAbsUrl, so if you are using a list, you need to use @FileRef

        The next change is that in your script, you must first use the makeAbsUrl(ItemURL) (from core.js) to get the absolute path that can be used by the service.

        I added this line to the start of the StartWorkflow function:

        var absUrl = makeAbsUrl(ItemURL)

        Then used absUrl in the service call instead of ItemURL

        Worked like a charm!

  16. Aaron says:

    I’m sorry, but I’m having an issue with xsl snippet to modify the DVWP. I see that can be pasted in using SPD, but where do I paste it in? Do I insert the code into the TD?

    • Aaron says:

      Ok, so I’ve figured that part out now. I put the xsl code in the TD in the Start Workflow column. However, when I click on the link, there is an error loading the javascript StartWorkflow function. When I debug, I get the error “object required”, which means that the function is not found. I have the javascript in a CEWP and have seen in the page source that the definition of the function is loaded before the call, so I don’t know why I’m getting the error.

  17. Dave Patel says:

    Just wanted to say thank you to Marc Anderson for his help in the past. He was very patient and helped me out during my beginning days of scripting.

    I also wanted to share with you a simple JavaScript option. It seems we sometimes over complicate things for our beginners out there doing Google searches.

    The below initiates a workflow to repair the ticket number assigned to the title field of a new form. The first section pulls the id from the url, the second initiates the workflow with a button click.


    var pathArray = window.location.href.split( ‘=’ );
    var newTicket = pathArray[1].replace(”&Source”, “”);
    element.onclick = repairTicket;
    function repairTicket() {
    window.location=” http://servername/sites/yoursite/Workflows/workflowname/repairticket.aspx?List=f2439d2d-79ee-4d38-835f-307c96bc9e63&ID=” + newTicket + “&TemplateID={a7176355-cf48-4a59-9340-3f39532bbb1d}&Source=http%3A%2F%2Fservername %2Ecom%2Fsites%2FGTSO%5Fyoursite%2Fdefault%2Easpx”;
    }


Notify me of comments to this article:


Speak and you will be heard.

We check comments hourly.
If you want a pic to show with your comment, go get a gravatar!