I have an angular app and I am using bpmn as a library. I have processes that have sub processes. What I am doing is creating a pdf document, and in that document attach the svg of the process which I already am able to do with this function:
/**
* Save diagram as a SVG
* @returns
*/
async saveDiagram() {
const { svg } = await this.bpmnJS.saveSVG({ format: true });
return svg;
}
Some processes have sub processes and what I need to do is when I click the extract pdf along side all the info I get I need to get the svg of the main process and all the sub processes that are part of this process. One process can have many sub processes. I have seen similar topics and have taken this example from the forum:
getSubProcesses() {
let canvas = this.bpmnJS.get('canvas');
let subprocesses = this.bpmnJS
.get("elementRegistry")
.filter(
(el) => el.type === ProcessObjectEnum.BPMN_SUB_PROCESS && el.hasOwnProperty("layer")
);
for (let i = 0; i < subprocesses.length; i++) {
// console.log(subprocesses[i]);
canvas.setRootElement(subprocesses[i]);
// console.log(JSON.stringify(canvas));
}
}
The problem is that when I click the print pdf, the printed document shows me one sub process the last one it iterates and skips the other sub processes and also the main process. Am I doing something wrong ? Is the thing I want to achieve possible. Appreciate the help.
I found the solution. Here it is for anyone who wants the same output as I do:
/**
* Gets main process and its subprocesses and converts
* them to svg files. Adds also the names and process id of the
* subprocesses
*/
async getSubProcesses() {
const svgCollection: { subProcessId: string; svg: string }[] = [];
// Save the SVG of the main process
const { svg: mainSvg } = await this.bpmnJS.saveSVG({ format: true });
const mainSvgObj = {
subProcessId: "",
svg: mainSvg
}
svgCollection.push(mainSvgObj);
// Get the XML of the main process
const { xml } = await this.bpmnJS.saveXML({ format: true });
// Create a hidden BPMN Modeler instance
const hiddenBpmnJS = new BpmnJS({
container: '#hiddenCanvasContainer',
});
// Import the XML into the hidden modeler
await hiddenBpmnJS.importXML(xml);
// Get the subprocesses
const hiddenCanvas = hiddenBpmnJS.get('canvas');
const subprocesses = hiddenBpmnJS.get('elementRegistry').filter(
(el) => el.type === 'bpmn:SubProcess' && el.hasOwnProperty('layer')
);
// Save the SVG of each subprocess
for (let i = 0; i < subprocesses.length; i++) {
hiddenCanvas.setRootElement(subprocesses[i]);
const { svg: subSvg } = await hiddenBpmnJS.saveSVG({ format: true });
const svgWithId = {
subProcessId: subprocesses[i].id,
svg: subSvg
}
svgCollection.push(svgWithId);
}
// Destroy the hidden BPMN modeler instance to free up resources
hiddenBpmnJS.destroy();
return svgCollection;
}
Great to read you found a solution to your problem.
BpmnViewer#saveSVG will save the currently available viewport. So indeed, it will not render the contents of embedded sub-process.
The library represents different sub-processes as root elements, and you’d be able to iterate through all available root elements, show them, and their graphical representation individually: