BPMN Expanded SubProcess

23 Aug 202510 minutes to read

BPMN Expanded SubProcess

An expanded subprocess is a BPMN shape that represents a complex process containing multiple child processes within it. Unlike collapsed subprocesses, expanded subprocesses display their internal structure and allow users to view and interact with the child processes directly. This makes them ideal for detailed process modeling where visibility into subprocess components is essential.

The expanded subprocess automatically adjusts its size to accommodate child elements and provides a container-like behavior for organizing related BPMN activities.

Create BPMN Expanded SubProcess

To create an expanded subprocess, configure the shape as activity and set collapsed to false. Enable the AllowDrop constraint to allow child nodes to be dropped inside the expanded subprocess container.

import { DiagramModule, BpmnDiagramsService, NodeConstraints, DiagramComponent, NodeModel, } from '@syncfusion/ej2-angular-diagrams'
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';

@Component({
    imports: [
        DiagramModule
    ],

    providers: [BpmnDiagramsService],
    standalone: true,
    selector: "app-container",
    template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" [getNodeDefaults] ='getNodeDefaults'>
        <e-nodes>
            <e-node id='node1' [offsetX]=350 [offsetY]=230 [shape]='shape1'></e-node>
           
        </e-nodes>
    </ejs-diagram>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    @ViewChild("diagram")
    public diagram?: DiagramComponent;
    public shape1 = {
        constraints: NodeConstraints.Default | NodeConstraints.AllowDrop,
        shape: 'Activity',
        type: 'Bpmn',
        activity: {
            activity: 'SubProcess',
            subProcess: {
                collapsed: false,
            },
        },

    }

    public getNodeDefaults(node: NodeModel): NodeModel {
        node.height = 200;
        node.width = 400;
        return node;
    }

}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Add BPMN Nodes into Expanded SubProcess

The processes property is an array collection that defines the child node values for the BPMN subprocess. This allows you to programmatically specify which BPMN elements should be contained within the expanded subprocess during initialization.

The following code example demonstrates how to define child processes within an expanded subprocess:

import { DiagramModule, BpmnDiagramsService, NodeConstraints,DiagramComponent } from '@syncfusion/ej2-angular-diagrams'
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
@Component({
    imports: [
        DiagramModule
    ],

    providers: [BpmnDiagramsService],
    standalone: true,
    selector: "app-container",
    template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" >
        <e-nodes>
            <e-node id='node1' [offsetX]=355 [offsetY]=230 [shape]='shape1' [height]=250 [width]=520></e-node>
            <e-node id='start'  [shape]='shape2'[height]=50 [width]=50 [margin]='margin' > </e-node>
           
        </e-nodes>
    </ejs-diagram>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    @ViewChild("diagram")
    public diagram?: DiagramComponent;
    public margin = { left: 50, top: 50 }
    public shape2 = {
        type: 'Bpmn', shape: 'Event',
    }
    public shape1 = {
        constraints: NodeConstraints.Default | NodeConstraints.AllowDrop,
        shape: 'Activity',
        type: 'Bpmn',
        activity: {
            activity: 'SubProcess',
            subProcess: {
                collapsed: false,
                processes: ['start'],

            },
        },
    }

}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Add BPMN Nodes into Expanded SubProcess at Runtime

Users can drag and drop BPMN nodes directly onto the expanded subprocess container during runtime. The expanded subprocess automatically maintains proper containment by monitoring the bounds of child elements. When a child element is resized or repositioned within the subprocess boundaries, the expanded subprocess container dynamically adjusts its size to accommodate the changes.

This interactive behavior ensures that the subprocess container always properly encompasses all its child processes while maintaining visual clarity and proper BPMN structure.

Expanded SubProcess BPMN Shape

Add and Remove Processes Programmatically

The expanded subprocess supports dynamic process management through dedicated methods. Use the addProcess method to add new child processes at runtime, and the removeProcess method to remove existing processes. These methods provide programmatic control over subprocess content without requiring manual manipulation.

The following example demonstrates how to implement dynamic process addition and removal:

import { DiagramModule, BpmnDiagramsService, NodeConstraints,DiagramComponent, NodeModel } from '@syncfusion/ej2-angular-diagrams'
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';

@Component({
    imports: [
        DiagramModule
    ],

    providers: [BpmnDiagramsService],
    standalone: true,
    selector: "app-container",
    template: `<button (click)="addProcess()">Add Process</button><button (click)="removeProcess()">Remove Process</button><ejs-diagram #diagram id="diagram" width="100%" height="580px" >
        <e-nodes>
            <e-node id='node1' [offsetX]=355 [offsetY]=230 [shape]='shape1' [height]=250 [width]=520></e-node>
            <e-node id='start'  [shape]='shape2'[height]=50 [width]=50 [margin]='margin' > </e-node>
            <e-node id='event2'  [shape]='shape3'[height]=50 [width]=50 [offsetX]=30 [offsetY]=40 [margin]='margin1' > </e-node>
           
        </e-nodes>
    </ejs-diagram>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    @ViewChild("diagram")
    public diagram?: DiagramComponent;
    public margin = { left: 50, top: 50 }
    public margin1 = { left: 150, top: 50 }
    public shape1 = {
        constraints: NodeConstraints.Default | NodeConstraints.AllowDrop,
        shape: 'Activity',
        type: 'Bpmn',
        activity: {
            activity: 'SubProcess',
            subProcess: {
                collapsed: false,
                processes: ['start'],
            },
        },
    }
    public shape2 = {
        type: 'Bpmn', shape: 'Event',
    }
    public shape3 = {
        type: 'Bpmn', shape: 'Event', event: { type: '' }
    }
    public addProcess(): void {
        let event1: NodeModel = (this.diagram as any).nameTable['event2'];
        (this.diagram as DiagramComponent).addProcess(event1, 'node1');
    }

    public removeProcess(): void {
        (this.diagram as DiagramComponent).removeProcess('event2');
    }

}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));