Integrating Cytoscape.js into Angular to Build Directed Acyclic Graphs (DAGs)

DAG-1

Visualizing processes, workflows, and data dependencies is a common requirement in modern applications. Directed Acyclic Graphs (DAGs) are a perfect fit for such scenarios. By integrating Cytoscape.js into an Angular application, you can create interactive and visually appealing DAGs with ease. This blog will guide you through the steps to integrate Cytoscape.js into Angular and use it to build a DAG.

In this blog, we'll walk through:

  • What is a Directed Acyclic Graph (DAG)?
  • What Cytoscape.js?
  • Setting Up Angular and Cytoscape.js
  • Implementing the DAG in Angular
  • Enhancing the DAG

What is a Directed Acyclic Graph (DAG)?

A Directed Acyclic Graph (DAG) is a graph structure where:

  • Edges are directed, meaning connections between nodes have a direction.
  • No cycles exist, ensuring that a node cannot loop back to itself.

Common Uses of DAGs

DAGs are widely used in various domains, including:

1. Workflow systems - Representing task flows in applications like Apache Airflow

2. Task scheduling - Managing execution order in computational tasks

3. Dependency resolution - Ensuring the correct order of operations (e.g., package managers)

4. Data lineage and tracking - Understanding dependencies in databases and analytics pipelines

What is Cytoscape.js?

Cytoscape.js is a lightweight yet powerful JavaScript library designed for rendering graphs and network data. It is highly customizable, interactive, and well-suited for building DAGs.

Key Features:

  • Node and edge customization – Modifies styles, labels, and appearances.
  • Multiple layouts – Supports hierarchical, circular, and force-directed layouts.
  • Event handling – Captures clicks, drags, and selection events
  • Extensibility – Easily extends with plugins and third-party libraries.

Gestures:

  • Grab and drag background to pan
  • Grab and drag nodes
  • Tap to select
  • Tap background to unselect

Setting Up Angular and Cytoscape.js

To use Cytoscape.js within an Angular application, follow these steps:

1. Install Cytoscape.js

Run the following command to install Cytoscape.js via npm:

npm install cytoscape

2. Generate a Graph Component

Create a new component to host the graph:

ng generate component graph

Implementing the DAG in Angular

1. Initialize Cytoscape.js

In the graph.component.html, add a container where the graph will render:

< div id="cy" style="width: 100%; height: 500px;">< /div>

In the graph.component.ts file, import Cytoscape.js and initialize it in the ngAfterViewInit lifecycle hook:

import { Component, AfterViewInit } from '@angular/core';
import cytoscape from 'cytoscape';

@Component({
  selector: 'app-graph',
  templateUrl: './graph.component.html',
  styleUrls: ['./graph.component.css'],
})
export class GraphComponent implements AfterViewInit {
  cy: any;
  
  ngAfterViewInit(): void {
    this.cy = cytoscape({
      container: document.getElementById('cy'), 
      elements: [
        { data: { id: 'A', label: 'Start' } },
        { data: { id: 'B', label: 'Task - 1' } },
        { data: { id: 'C', label: 'Task - 2' } },
        { data: { id: 'D', label: 'End' } },
        { data: { source: 'A', target: 'B' } },
        { data: { source: 'A', target: 'C' } },
        { data: { source: 'B', target: 'D' } },
        { data: { source: 'C', target: 'D' } },
      ],

      style: [
        {
          selector: 'node',
          style: {
            'background-color': '#0074D9',
            'label': 'data(label)',
            'text-halign': 'center',
            'text-valign': 'center',
            'color': '#fff',
          },
        },
        {
          selector: 'edge',
          style: {
            'width': 3,
            'line-color': '#0074D9',
            'target-arrow-color': '#0074D9',
            'target-arrow-shape': 'triangle',
          },
        },
      ],

      layout: {
        name: 'breadthfirst',
        directed: true,
      },
    });
  }
}
DAG Chart

2. Add Dynamic Layouts

For DAGs, hierarchical layouts such as breadthfirst or plugins like dagre are ideal to improve readability.

Configure the layout dynamically:

this.cy.layout({
  name: 'breadthfirst',
  directed: true,
  spacingFactor: 1.5,
}).run();

3. Enable Interactivity

Handle user interactions, such as clicking on nodes or edges:

this.cy.on('tap', 'node', (event) => {
  const node = event.target;
  alert(`You clicked on node: ${node.data('label')}`);
});

Enhancing the DAG

1. Style Nodes Dynamically

Change node styles based on their state or user interaction:

this.cy.on('mouseover', 'node', (event) => {
const node = event.target;
     node.style({
     'background-color': '#87CEEB',
     'label': 'data(name)',
     'shape': 'roundrectangle',
     'text-valign': 'center',
     'text-halign': 'center',
     'width': '150px',
     'height': '50px',
     'border-width': 0,
     'text-wrap': 'wrap',               
     'text-max-width': '150px',       
     'text-overflow-wrap': 'anywhere'
   });
  });

2. Highlight Dependencies

Modify styles to emphasize dependencies:

this.cy.elements().addClass('highlight');

this.cy.style()
  .selector('.highlight')
  .style({
    'line-color': 'red',
    'target-arrow-color': 'red',
  })
  .update();

3. Add Real-Time Updates

Modify the graph dynamically, such as adding or removing nodes and edges:

this.cy.add({ data: { id: 'E', label: 'New Task' } });
this.cy.add({ data: { id: 'F', label: 'Another Task' } });
this.cy.add({ data: { source: 'D', target: 'E' } });
this.cy.add({ data: { source: 'E', target: 'F' } })

Example Use Case: Workflow Management

Imagine you’re building a workflow tool. Using Cytoscape.js, you can:

  • Represent tasks as nodes and dependencies as edges.
  • Allow users to define workflows dynamically.
  • Provide real-time updates as tasks are added or completed.
  • Highlight critical paths or bottlenecks visually.

Why Use Cytoscape.js for DAGs in Angular?

  • Customizable: Fine-tune styles, layouts, and behaviors.
  • Scalable: Handle large and complex graphs efficiently.
  • Extensible: Add plugins for advanced layouts and interactions.
  • Angular-Friendly: Integrates seamlessly with Angular components.

Final Thoughts

Integrating Cytoscape.js into Angular is a straightforward way to build interactive and visually appealing DAGs. By following this guide, you can create a graph visualization tailored to your specific needs. Experiment with layouts, styles, and interactivity to make your application stand out.