Nodes, edges, handles & performance
Feature recipes aligned with the ngx-vflow docs IA — implemented with ngx-workflow’s API.
createNode / createEdge
import { createNode, createEdge } from 'ngx-workflow';
const nodes = [
createNode({ label: 'A', position: { x: 0, y: 0 } }),
createNode({ label: 'B', position: { x: 200, y: 0 } }),
];
const edges = [
createEdge({ source: nodes[0].id, target: nodes[1].id, type: 'bezier' }),
];HTML & SVG template nodes
Use type: 'html-template' or type: 'svg-template' with projected templates.
<ngx-workflow-diagram [nodes]="nodes" [edges]="edges">
<ng-template #nodeHtmlTemplate let-ctx>
<div class="card">{{ ctx.data?.title }}</div>
</ng-template>
</ngx-workflow-diagram>Custom edges
Register components via NGX_WORKFLOW_EDGE_TYPES / [edgeTypes], or pass [edgeTemplate].
providers: [{
provide: NGX_WORKFLOW_EDGE_TYPES,
useValue: { 'glow': GlowEdgeComponent }
}]
// edge.type = 'glow'Direction-aware bezier routing
Pass sourceHandle / targetHandle so curves leave and enter the correct ports. Vertical stacks should use bottom → top (or top → bottom).
createEdge({
source: 'start',
target: 'end',
type: 'bezier',
sourceHandle: 'bottom',
targetHandle: 'top',
});Connection & selection modes
connectionMode="loose"— handles optional (default).connectionMode="strict"— both handles required.selectionMode="partial"— lasso intersects node (default).selectionMode="full"— node must be fully inside the lasso.
Typed change streams
Listen to (nodeChanges) / (edgeChanges) for granular updates. Filter with host inputs filterNodeTypes / filterEdgeTypes and (filteredNodeChanges) / (filteredEdgeChanges).
<ngx-workflow-diagram
[nodes]="nodes"
[edges]="edges"
[filterNodeTypes]="['position', 'select']"
(filteredNodeChanges)="onFiltered($event)"
(nodeChanges)="onAll($event)"
/>Workflow Legend & Custom API Inspector
Combine <ngx-workflow-panel> with [showPropertiesSidebar]="false" and (nodeDoubleClick) to render rich status cards and fetch backend schemas on demand.
<ngx-workflow-diagram
[nodes]="nodes()"
[edges]="edges()"
[showPropertiesSidebar]="false"
(nodeDoubleClick)="onNodeDoubleClick($event)"
(paneClick)="closeInspector()"
>
<!-- Fixed Workflow Legend Panel -->
<ngx-workflow-panel [position]="'top-right'" [style]="{ minWidth: '280px' }">
<div class="legend-card">
<h4>Workflow Legend</h4>
<div class="item"><span class="dot bg-blue"></span> Active Ingestion</div>
<div class="item"><span class="dot bg-emerald"></span> Database Sink</div>
</div>
</ngx-workflow-panel>
<!-- Contextual API Inspector Panel on Double-Click -->
@if (inspectorOpen()) {
<ngx-workflow-panel [position]="'center-right'" [style]="{ zIndex: 30 }">
<div class="inspector-card glass-panel">
<h4>{{ activeNode()?.label }} API Schema</h4>
<p>Endpoint: {{ activeConfig()?.endpoint }}</p>
<button (click)="saveAndSync()">Save & Sync API</button>
</div>
</ngx-workflow-panel>
}
</ngx-workflow-diagram>Live mini demo
Interact with the canvas to see nodeChanges…