Core Concepts & Reactive Architecture
Understanding the internal mechanics of ngx-workflow will help you build complex interactive diagram editors efficiently.
1. Signals State Management
At the core of ngx-workflow is DiagramStateService. Instead of relying on continuous change detection cycles or heavy RxJS subscription chains for mouse movements, diagram state is modeled using Angular signal() and computed() primitives:
// State Architecture Overview
diagramState = {
nodes: signal<WorkflowNode[]>([]),
edges: signal<WorkflowEdge[]>([]),
viewport: signal<ViewportState>({ x: 0, y: 0, zoom: 1 }),
selectedNodeIds: signal<Set<string>>(new Set())
};2. Viewport Transform & Canvas Coordinates
The diagram viewport handles pan (translate) and zoom (scale). All node positions are maintained in absolute graph space (x, y), while the viewport transform matrix converts them to DOM client coordinates:
DOM_X = (Graph_X * Zoom) + Pan_X
DOM_Y = (Graph_Y * Zoom) + Pan_Y When users drag nodes, ngx-workflow automatically converts mouse offset events back into graph space coordinates, taking the current zoom level and pan offset into account.
3. Handles, Ports & Connecting
Connections originate and terminate at Handles (ports). Default nodes expose top / right / bottom / left based on node.ports (0=none … 4=all).
- Manual connect: drag from one port to another — a preview edge follows the pointer.
- Auto-connect: drag a node near another (within
[proximityThreshold]) to snap a link. - Limits:
handleConfig[port].maxConnections→maxConnectionsPerPort→[maxConnectionsPerHandle]. - Handles register with
HandleRegistryServicefor typeddataTypechecks and connectability.
// Manual + limited connections
<ngx-workflow-diagram
[nodes]="nodes()"
[edges]="edges()"
[maxConnectionsPerHandle]="2"
(connectStart)="..."
(connect)="..."
(edgesChange)="edges.set($event)"
/>4. ELK.js Auto-Layout Engine
ngx-workflow includes AutoLayoutService which delegates layout computation to the Eclipse Layout Kernel (ELK). You can invoke auto-layout at any time:
import { AutoLayoutService } from 'ngx-workflow';
// Inject service in your component
private autoLayout = inject(AutoLayoutService);
async arrangeDiagram() {
// Directions: 'TB' (Top-to-Bottom), 'LR' (Left-to-Right), 'BT', 'RL'
await this.autoLayout.applyLayout('LR');
}