Need to start a Nintex workflow from within your TypeScript application? Here is a service class which wraps all the gubbins of the asmx service and can be called via a single function that returns a promise.
Parameters:
Workflow Name
List Name
Item ID
Workflow Parameters (as an object {parameter:value,...} ).
import { Web } from '@pnp/sp'; import { xml2json } from 'xml-js'; export class NintexWfService { private envStartNintexWorkflow: string; private web: Web; private digest: string; constructor() { this.web = new Web(_spPageContextInfo.webAbsoluteUrl); this.envStartNintexWorkflow = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" + "<soap:Body>" + "<StartWorkflowOnListItem xmlns=\"http://nintex.com\">" + "<itemId>ITEM_ID</itemId>" + "<listName>LIST_NAME</listName>" + "<workflowName>WORKFLOW_NAME</workflowName>" + "<associationData>WORKFLOW_DATA</associationData>" + "</StartWorkflowOnListItem>" + "</soap:Body>" + "</soap:Envelope>"; this.digest = ''; } public startNintexWorkflow(wfName: string, listName: string, itemId: number, wfParameters?: {}): Promise<any> { return new Promise((resolve, reject) => { this.getDigest() .then(digest => { let xmlParameters: string = ''; if (wfParameters) { let totalParams: number = 0; xmlParameters = '<Data>'; Object.keys(wfParameters).map((k, i) => { if (wfParameters[k]) { xmlParameters += '<' + k + '>' + wfParameters[k] + '</' + k + '>'; totalParams++; } }); xmlParameters += '</Data>'; if (totalParams > 0) { xmlParameters = this.xmlEscape(xmlParameters); } else { xmlParameters = ''; } } const url = _spPageContextInfo.webAbsoluteUrl + '/_vti_bin/NintexWorkflow/Workflow.asmx'; const headerData = { 'Accept': 'text/xml', 'Content-Type': 'text/xml; charset=utf-8', 'SOAPAction': 'http://nintex.com/StartWorkflowOnListItem', 'X-RequestDigest': digest }; let soap = this.envStartNintexWorkflow; soap = soap.replace('ITEM_ID', <string>itemId.toString()); soap = soap.replace('LIST_NAME', <string>listName); soap = soap.replace('WORKFLOW_NAME', <string>wfName); soap = soap.replace('WORKFLOW_DATA', xmlParameters); return fetch( url, { method: 'POST', headers: headerData, body: soap, credentials: 'same-origin' } ); }) .then((data) => { if (!data.ok) { reject(data.statusText) } else { data.clone().text().then(xml => { let wfGuid = ''; try { var jsonRes: any = JSON.parse(xml2json(xml)); wfGuid = jsonRes.elements[0].elements[0].elements[0].elements[0].elements[0].text; } catch (err) { wfGuid = ''; } resolve(wfGuid); }); } }) .catch(err => { reject(err); }); }); } private xmlEscape(str: string): string { return String(str).replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(/</g, '<').replace(/>/g, '>'); } private getDigest(): Promise<any> { return new Promise((resolve, reject) => { if (this.digest !== '') { resolve(this.digest); } else { fetch( _spPageContextInfo.webAbsoluteUrl + '/_api/contextinfo', { method: 'POST', headers: { 'Accept': 'application/json; odata=verbose', 'content-type': 'application/json; odata=verbose' }, credentials: 'same-origin' }) .then((response) => { return response.text(); }) .then((data) => { const jsonVal = JSON.parse(data); if (jsonVal.d && jsonVal.d.GetContextWebInformation && jsonVal.d.GetContextWebInformation.FormDigestValue) { this.digest = jsonVal.d.GetContextWebInformation.FormDigestValue; resolve(this.digest); } else { reject(jsonVal); } }) .catch((response) => { reject(response); }); } }); } }
Notice we’re using fetch() to make the calls.
To call it:
const nwfs = new NintexWfService(); nwfs.startNintexWorkflow( 'Industrious Workflow', 'Documents', 321, { MyParameter: 'MyP@r@m3t3r' }) .then((wfId) => { console.log('Workflow GUID: ' + wfId + ' started!'); });