Below is some sample code to provision a workflow on the host web from your app web. This sample code is in one block for demo purposes. It makes 4 asynchronous calls to SharePoint to complete successfully.

In the event you’d want to define in your App a workflow that would run on a list in the host web this is the code you would use to deploy (move it from App to Host) and attach it to a list in the host web.

NOTE: you must include a reference to “/_layouts/15/SP.WorkflowServices.js”

   var attachWorkflow = function(workflowName, workflowListName, workflowHistoryListName, workflowTasksListName) {

        //Using the App Web as the client context
		clientContext = new SP.ClientContext.get_current();
   
		//Get the host web URL from the query string params
		//I have a function getHostWebUrl() - which is not included.
		//http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
		var hostWebUrl = getHostWebUrl();
		
		//Using the hostWebContext as an AppContextSite
        hostWebContext = new SP.AppContextSite(clientContext, hostWebUrl);
        
		//Get the Workflow Services Manager for the Host web, NOTE: you initialize it with the clientContext & the hostWebContext Web)
        var hostWebWorkflowServicesManager = new SP.WorkflowServices.WorkflowServicesManager.newObject(clientContext, hostWebContext.get_web());
        var hostWebWorkflowDeploymentService = hostWebWorkflowServicesManager.getWorkflowDeploymentService();
        var hostWebSubscriptionService = hostWebWorkflowServicesManager.getWorkflowSubscriptionService();

		//Get the Workflow Services Manager for the App web 
        var workflowServicesManager = new SP.WorkflowServices.WorkflowServicesManager(clientContext, clientContext.get_web());
        var workflowDeploymentService = workflowServicesManager.getWorkflowDeploymentService();
        var workflowDeploymentServiceDefinitions = workflowDeploymentService.enumerateDefinitions(false);

		//Load all the Workflow Definitions from the App web
        clientContext.load(workflowDeploymentServiceDefinitions);
        clientContext.executeQueryAsync(function () {

			//Get the enumerator for all the workflow definitions in the App web
            var workflowDefinitions = workflowDeploymentServiceDefinitions.getEnumerator();
            while (workflowDefinitions.moveNext()) {

				//set the current definition to a variable
                var workflowDefinition = workflowDefinitions.get_current();
				//test, trying to locate your workflow in the App web
                if (workflowDefinition.get_displayName() === workflowName) {

					//now grab the xaml definition of the selected workflow
                    var workflowXaml = workflowDefinition.get_xaml();

					//define a new workflow and assign it xaml & name
                    var newWorkflow = new SP.WorkflowServices.WorkflowDefinition.newObject(clientContext, hostWebContext.get_web());
                    newWorkflow.set_xaml(workflowXaml);
                    newWorkflow.set_displayName(workflowName);
					
					//using the host webs Workflow Deployment Service, save the workflow.
                    hostWebWorkflowDeploymentService.saveDefinition(newWorkflow);
                    
					//load the new workflow and initialize the Id
					clientContext.load(newWorkflow, "Id");
					//this query will save your workflow to the host web
                    clientContext.executeQueryAsync(function() {

						//publish the workflow on the host web
                        hostWebWorkflowDeploymentService.publishDefinition(newWorkflow.get_id());
						
						//getting all the lists that the workflow will attach to
						//these lists already created on the host web
                        var targetList = hostWebContext.get_web().get_lists().getByTitle(workflowListName);
                        var historyList = hostWebContext.get_web().get_lists().getByTitle(workflowHistoryListName);
                        var tasksList = hostWebContext.get_web().get_lists().getByTitle(workflowTasksListName);

						//loading the lists & initialize the Id
                        clientContext.load(targetList, "Id");
                        clientContext.load(historyList, "Id");
                        clientContext.load(tasksList, "Id");

						//this query will publish the workflow and get the required list id's for the next step
                        clientContext.executeQueryAsync(function() {

								//creating a new workflow subscription
                                var subscription = new SP.WorkflowServices.WorkflowSubscription(clientContext, hostWebContext.get_web());

								//setting some properties of the subscription
                                subscription.set_name(workflowName + "-ItemAdded");
                                subscription.set_enabled(true);
                                subscription.set_definitionId(newWorkflow.get_id().toString());
                                subscription.set_eventSourceId(targetList.get_id());
                                subscription.set_eventTypes(["ItemAdded"]);

								subscription.setProperty("TaskListId", tasksList.get_id().toString());
                                subscription.setProperty("HistoryListId", historyList.get_id().toString());
                                subscription.setProperty("FormData", "");

								//attaching the subscription to the target list 
                                hostWebSubscriptionService.publishSubscriptionForList(subscription, targetList.get_id());

								//this query will execute the creation of the new subscription and adding attaching the subscription to the target list on the host web
                                clientContext.executeQueryAsync(function() {
                                    console.log("Workflow : \"" + workflowName + "\" successfully added to list : \"" + workflowListName + "\"");
                                }, function(sender, args) {
                                    console.log("Workflow : " + workflowName + " not successfully added to list : " + workflowListName);
                                    console.log("Reason : " + args.get_message() + "");
                                });
                            },
                            function(sender, args) {
                                console.log("Failed to get workflow list IDs");
                                console.log("Reason : " + args.get_message() + "");
                            });

                    }, function(sender, args) {
                        console.log("Failed to create the workflow definition");
                        console.log("Reason : " + args.get_message() + "");
                    });
                }
            }
        }, function (sender, args) {
            console.log("Could not find workflow : " + workflowName);
            console.log("Reason : " + args.get_message() + "");
        });
    };
Comments
  • cv
    Posted at 5:29 pm October 7, 2015
    cv
    Reply
    Author

    Nice Article, Thanks for sharing.
    I want to know is it possible to deploy custom workflow activities from App web to hostweb?

    Thank you

    • Spyros
      Posted at 5:32 pm January 17, 2016
      Spyros
      Reply
      Author

      Hi cv,

      Did you ever figure this out? It seems that if your workflows contain custom activities, you get an error trying to deploy the workflows from app web to host web. Do you know if there is a way of programmatically deploy the actvities to host web?

      Thanks

  • Soyeb Malek
    Posted at 6:33 am September 24, 2015
    Soyeb Malek
    Reply
    Author

    Great Job Thomas..
    Perfect Code.. Thanks for sharing..

  • Mike
    Posted at 1:24 pm March 3, 2015
    Mike
    Reply
    Author

    I trying your code and it’s creating the workflow and association but not carrying over the initiation form. Is there something that needs to be set on the subscription object or elsewhere to set the workflow to first call the init form?

  • Shangar
    Posted at 10:49 pm December 8, 2014
    Shangar
    Reply
    Author

    Hi,

    How to implement this to SharePoint-Host Apps? Event Handler is not support to SharePoint-Hosted Apps.

    Thank you.

    • Thomas Daly
      Posted at 8:30 pm January 3, 2015
      Thomas Daly
      Reply
      Author

      This article is based on SharePoint hosted apps. To provision to the SharePoint site you would need to implement a configuration screen in your app.

      • Sri
        Posted at 1:00 pm February 27, 2015
        Sri
        Reply
        Author

        Hi Thomas,
        Can I use above code to associate workflow from app web to host web on ONPREMISES SharePoint 2013. Seems everyone are talking about associating on SharePoint online only. Is there a way to associate a app workflow to already created host web in SharePoint ONPREMISES.

        Thank you

  • Dedek
    Posted at 7:26 am June 16, 2014
    Dedek
    Reply
    Author

    Good job, this is awesome piece of code! Very useful, thanks for sharing.

  • Leave a Reply

    This site uses Akismet to reduce spam. Learn how your comment data is processed.