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!');
});