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() + ""); }); };
Nice Article, Thanks for sharing.
I want to know is it possible to deploy custom workflow activities from App web to hostweb?
Thank you
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
Great Job Thomas..
Perfect Code.. Thanks for sharing..
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?
Hi,
How to implement this to SharePoint-Host Apps? Event Handler is not support to SharePoint-Hosted Apps.
Thank you.
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.
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
Good job, this is awesome piece of code! Very useful, thanks for sharing.