Angular  

Creating a Browser-Based Workflow Simulator in Angular (Drag Nodes → Simulate Execution)

Building a browser-based workflow simulator is one of the most useful features for modern enterprise applications. Sectors like manufacturing, aviation, finance, insurance, and IT operations commonly need custom workflows. Users want to visually create steps, connect nodes, define rules, run simulations, and see how the workflow behaves before pushing it to the live environment.

This article explains how to build a production-ready Workflow Simulator using Angular.
The system supports:

  • Drag-and-drop node creation

  • Graph-based workflow builder

  • Branching paths and decision nodes

  • Node configuration panels

  • Execution simulation with event logs

  • Validation of loops, unreachable nodes, and broken paths

  • Pluggable rule engine

  • JSON-based storage and replay

  • Real-time visualisation of execution path

The goal is to build an Angular-based workflow editor that functions like lightweight versions of Camunda Modeler, Node-RED, or n8n, but fully customisable for your product.

Why Build a Workflow Simulator

Typical enterprise systems contain long-running or multi-step business processes. Before executing workflows in production, developers and business users need a safe sandbox to test logic.

A browser-based simulator allows:

  • Quick iteration

  • Visual understanding of flows

  • Troubleshooting of decision logic

  • Validation before saving workflows

  • Replaying actual data

  • Training and demonstration

Most importantly, it reduces rework and production issues.

High-Level Features Required

A workflow simulator must include:

  1. Node palette (Start, Task, Decision, API Call, Script, End).

  2. Drag-and-drop canvas.

  3. Connectors between nodes.

  4. Node configuration (name, rules, conditions, inputs).

  5. JSON export/import of the workflow.

  6. Execution engine to simulate the workflow step-by-step.

  7. Visual highlight of execution path.

  8. Validation engine.

  9. Undo/redo support.

  10. Event logs and breakpoints.

This article focuses on the Angular implementation, core architecture, and execution simulation.

High-Level Architecture

The system is divided into:

  • Canvas Module

  • Nodes Module

  • Connection Engine

  • Workflow Engine (simulation)

  • Persistence Module

  • Validation Module

  • UI Components (palette, config panel)

Architecture Workflow Diagram

           +------------------------------+
           |         Workflow UI          |
           +------------------------------+
             |          |            |
             |          |            |
             v          v            v
     +------------+  +-------+  +------------+
     | Node       |  | Edge  |  | Config     |
     | Palette    |  | Layer |  | Panel      |
     +------------+  +-------+  +------------+
             |          |
             |  Drag    | Connections
             v          v
        +---------------------+
        | Workflow Canvas     |
        +----------+----------+
                   |
                   v
        +------------------------+
        | Workflow Engine (Core) |
        +----------+-------------+
                   |
        Validate   |    Simulate
                   v
        +-------------------------+
        | Execution Simulator     |
        +-------------------------+
                   |
                   v
           +---------------+
           | Event Logs    |
           +---------------+

Flowchart: Workflow Execution Simulation

          +--------------------------+
          | Load Workflow Definition |
          +-------------+------------+
                        |
                        v
            +-----------+-----------+
            | Identify Start Node   |
            +-----------+-----------+
                        |
                        v
            +-----------+-----------+
            | Execute Current Node  |
            +-----------+-----------+
                        |
            +-----------+------------+
            | Node has outgoing path?|
            +------+-----------------+
                   | Yes
                   v
          +--------+--------+
          | Evaluate Rules  |
          +--------+--------+
                   |
         +---------+--------+
         | Select Next Node |
         +---------+--------+
                   |
                   v
         +---------+--------+
         | Move to Next Node|
         +---------+--------+
                   |
                   v
        Repeat until End node reached

Designing the Workflow Data Model

A workflow is a directed graph. Each node represents a step, and each edge represents the flow.

Node Structure

export interface WorkflowNode {
  id: string;
  type: 'start' | 'task' | 'decision' | 'api' | 'script' | 'end';
  name: string;
  position: { x: number; y: number };
  config?: any;
}

Edge Structure

export interface WorkflowEdge {
  id: string;
  from: string;
  to: string;
  condition?: string; // expression or rule
}

Workflow Definition

export interface WorkflowDefinition {
  nodes: WorkflowNode[];
  edges: WorkflowEdge[];
}

Building the Canvas in Angular

You will use these libraries/tools:

  • Angular CDK DragDrop Module

  • HTML canvas or SVG for rendering

  • RxJS for state management

  • A lightweight graph calculation library (optional)

Basic Canvas Component

@Component({
  selector: 'app-workflow-canvas',
  templateUrl: './workflow-canvas.component.html',
  styleUrls: ['./workflow-canvas.component.css']
})
export class WorkflowCanvasComponent {
  @Input() workflow!: WorkflowDefinition;

  onNodeDrag(event: CdkDragMove, node: WorkflowNode) {
    node.position.x = event.pointerPosition.x;
    node.position.y = event.pointerPosition.y;
  }
}

Canvas Template

<div class="canvas-area">
  <div *ngFor="let node of workflow.nodes"
       class="node"
       cdkDrag
       [style.left.px]="node.position.x"
       [style.top.px]="node.position.y">
       {{ node.name }}
  </div>

  <svg class="edge-layer">
    <ng-container *ngFor="let edge of workflow.edges">
      <line
        [attr.x1]="getNode(edge.from).position.x + 50"
        [attr.y1]="getNode(edge.from).position.y + 20"
        [attr.x2]="getNode(edge.to).position.x"
        [attr.y2]="getNode(edge.to).position.y"
        stroke="black"
        stroke-width="2" />
    </ng-container>
  </svg>
</div>

Implementing Drag-and-Drop Node Palette

A simple palette:

<div class="palette">
  <button (click)="addNode('task')">Add Task</button>
  <button (click)="addNode('decision')">Add Decision</button>
  <button (click)="addNode('api')">Add API Call</button>
</div>

Add Node Logic

addNode(type: string) {
  const newNode: WorkflowNode = {
    id: crypto.randomUUID(),
    type,
    name: `${type} node`,
    position: { x: 100, y: 100 }
  };

  this.workflow.nodes.push(newNode);
}

Adding Connectors Between Nodes

Common approach:

  1. Click first node.

  2. Click second node.

  3. Create edge.

Add Edge Logic

addEdge(fromId: string, toId: string) {
  this.workflow.edges.push({
    id: crypto.randomUUID(),
    from: fromId,
    to: toId
  });
}

Adding Node Configuration Panel

This allows editing:

  • Name

  • Inputs

  • Conditions

  • Output fields

  • API parameters

  • Decision expressions

Sample Configuration Panel

<div class="config-panel" *ngIf="selectedNode">
  <h3>Node Configuration</h3>
  <label>Name:
    <input [(ngModel)]="selectedNode.name" />
  </label>

  <label *ngIf="selectedNode.type === 'decision'">
    Condition:
    <input [(ngModel)]="selectedNode.config.condition" />
  </label>
</div>

The Workflow Execution Engine

The Workflow Engine runs the workflow.
This includes:

  • Loading workflow JSON

  • Finding the start node

  • Executing each node

  • Evaluating rules

  • Logging events

  • Highlighting visited nodes

Engine Structure

export class WorkflowEngine {
  constructor(private workflow: WorkflowDefinition) {}

  private logs: string[] = [];

  execute() {
    let currentNode = this.findStartNode();

    while (currentNode && currentNode.type !== 'end') {
      this.logs.push(`Executing: ${currentNode.name}`);
      currentNode = this.getNextNode(currentNode);
    }

    this.logs.push('Reached end node');
    return this.logs;
  }
}

Rule Evaluation for Decision Nodes

Rules may be:

  • JavaScript expressions

  • JSON-based rule definitions

  • Condition strings

Example Rule Evaluation

evaluateCondition(condition: string, context: any): boolean {
  const fn = new Function("context", `return ${condition}`);
  return fn(context);
}

For large enterprise systems, use a safe rule engine instead of dynamic functions.

Simulating Execution Step-by-Step

Support:

  • Automatic play

  • Manual step-by-step

  • Breakpoints

Step Mode Example

step() {
  if (!this.currentNode) {
    this.currentNode = this.findStartNode();
    return this.currentNode;
  }

  this.currentNode = this.getNextNode(this.currentNode);
  return this.currentNode;
}

Visualising Execution Path

When the simulator runs:

  • Highlight the active node

  • Highlight the traversed edges

  • Dim inactive nodes

Canvas Highlighting Example

.node.active {
  border: 2px solid blue;
}

.edge.active {
  stroke: blue;
}

You will toggle CSS classes based on execution logs.

Validations Before Simulation

Essential validations:

  1. Workflow must contain exactly one start node.

  2. All nodes must be reachable from start.

  3. No cycles unless allowed.

  4. Decision nodes must contain valid conditions.

  5. All edges must reference valid node IDs.

Example Validation Function

validateWorkflow(workflow: WorkflowDefinition): string[] {
  const errors: string[] = [];

  const startNodes = workflow.nodes.filter(n => n.type === 'start');
  if (startNodes.length !== 1) {
    errors.push('Workflow must contain exactly one start node.');
  }

  // Additional validations…

  return errors;
}

JSON Export and Import

The workflow editor must support saving and loading.

Export

downloadJSON() {
  const json = JSON.stringify(this.workflow);
  // download logic
}

Import

uploadWorkflow(json: string) {
  this.workflow = JSON.parse(json);
}

Undo / Redo Support

Use an RxJS BehaviorSubject to push state snapshots.

Example

history: WorkflowDefinition[] = [];
historyIndex = -1;

pushState() {
  this.history.push(JSON.parse(JSON.stringify(this.workflow)));
  this.historyIndex++;
}

Undo

undo() {
  if (this.historyIndex > 0) {
    this.historyIndex--;
    this.workflow = JSON.parse(JSON.stringify(this.history[this.historyIndex]));
  }
}

Real-World Challenges and Best Practices

  1. Performance drops when rendering more than 200 nodes.
    Use canvas or WebGL for large workflows.

  2. Users need zooming and panning.
    Implement with CSS transforms.

  3. Complex connectors require bezier curves.
    Use SVG path elements.

  4. Decision rules get messy.
    Integrate a rules engine (Nools, JSON-rules-engine).

  5. Autosaving is essential.
    Persist state in localStorage every few seconds.

  6. Multi-user collaboration.
    Use WebSockets and operational transforms.

  7. Prevent invalid node drops.
    Add guards and context checks.

Production-Level Recommendations

  • Use a state management library (NgRx or Akita) for storing workflow state.

  • Use RxJS Subjects for canvas events.

  • Debounce drag events to reduce change detection load.

  • Generate node IDs using crypto APIs for uniqueness.

  • Allow theming and custom node templates.

  • Include snap-to-grid behaviour for cleaner diagrams.

  • Create extension hooks for future custom nodes.

Conclusion

A browser-based workflow simulator is a powerful and reusable tool for any enterprise Angular application. By combining a graph-based canvas, configurable nodes, a robust execution engine, and a validation system, you can build a complete workflow modelling and testing system inside the browser.

What makes this solution truly valuable is its flexibility. It doesn’t depend on any external engine and can be adapted for HR approvals, manufacturing processes, IT automation, financial rules, document processing, and more.