How to Use Mermaid.js in Angular: Complete Integration Guide
Step-by-step guide to integrating Mermaid.js diagrams in Angular applications. Learn how to render flowcharts, sequence diagrams, and more inside Angular components.
# How to Use Mermaid.js in Angular: Complete Integration Guide
Angular developers often need to embed diagrams inside their apps — architecture overviews, API flow charts, state machines, and more. Mermaid.js is the go-to library for text-based diagrams, and it integrates cleanly with Angular once you know the pattern. This guide walks you through everything from installation to reusable components.
Why Mermaid.js with Angular?
Mermaid.js lets you write diagrams as plain text and render them as SVG. It fits naturally into Angular apps because:
- No designer needed — developers write diagram code alongside app code.
- Version-control friendly — text diffs, not binary image files.
- Dynamic diagrams — bind Angular component data directly to diagram definitions.
- Zero external service — renders fully in the browser.
Installation
Install Mermaid via npm:
npm install mermaidMermaid ships with TypeScript types built-in, so no @types package is needed.
Basic Angular Component
Create a reusable MermaidComponent that accepts a diagram definition string:
// mermaid.component.ts
import {
Component, Input, OnChanges,
ElementRef, ViewChild, AfterViewInit
} from '@angular/core';
import mermaid from 'mermaid';
@Component({
selector: 'app-mermaid',
standalone: true,
template: `<div #container></div>`,
})
export class MermaidComponent implements AfterViewInit, OnChanges {
@Input() diagram = '';
@ViewChild('container') container!: ElementRef<HTMLDivElement>;
private initialized = false;
ngAfterViewInit() {
mermaid.initialize({ startOnLoad: false, theme: 'default' });
this.initialized = true;
this.render();
}
ngOnChanges() {
if (this.initialized) this.render();
}
private async render() {
if (!this.diagram) return;
const id = 'mermaid-' + Math.random().toString(36).slice(2);
const { svg } = await mermaid.render(id, this.diagram);
this.container.nativeElement.innerHTML = svg;
}
}Use it in any parent template:
<app-mermaid [diagram]="myDiagram"></app-mermaid>Example: Flowchart
flowchart TD
A[User Request] --> B{Auth Check}
B -->|Authenticated| C[Load Dashboard]
B -->|Unauthenticated| D[Redirect to Login]
C --> E[Fetch Data from API]
E --> F[Render Components]Try in Editor →Bind the diagram string from your Angular component class:
export class AppComponent {
myDiagram = `
flowchart TD
A[User Request] --> B{Auth Check}
B -->|Authenticated| C[Load Dashboard]
B -->|Unauthenticated| D[Redirect to Login]
`;
}Example: Sequence Diagram for API Calls
sequenceDiagram
participant Browser
participant Angular
participant API
Browser->>Angular: Click "Load Data"
Angular->>API: GET /api/data
API-->>Angular: 200 OK + JSON
Angular-->>Browser: Render TableTry in Editor →This pattern is perfect for documenting Angular services that communicate with backends.
Dynamic Diagrams from Component State
One of Angular's strengths is two-way data binding. Use a computed property to generate diagrams from live data:
import { Component } from '@angular/core';
@Component({
selector: 'app-pipeline',
template: `<app-mermaid [diagram]="pipelineDiagram"></app-mermaid>`,
})
export class PipelineComponent {
stages = ['Build', 'Test', 'Deploy'];
get pipelineDiagram(): string {
const nodes = this.stages.map((s, i) => `${i}[${s}]`).join(' --> ');
return `flowchart LR\n ${nodes}`;
}
}As the stages array updates, the diagram re-renders automatically through ngOnChanges.
Theming
Mermaid supports multiple built-in themes. Match your Angular app's dark/light mode:
mermaid.initialize({
startOnLoad: false,
theme: document.documentElement.classList.contains('dark') ? 'dark' : 'default',
});Available themes: default, forest, dark, neutral, base.
Server-Side Rendering (Angular Universal)
Mermaid.js requires a DOM and will throw during SSR. Guard the initialization:
import { isPlatformBrowser } from '@angular/common';
import { PLATFORM_ID, inject } from '@angular/core';
const platformId = inject(PLATFORM_ID);
ngAfterViewInit() {
if (isPlatformBrowser(platformId)) {
mermaid.initialize({ startOnLoad: false });
this.render();
}
}Lazy Loading Mermaid
Mermaid adds ~1MB to your bundle. For large apps, lazy-load it only when a diagram is needed:
private async render() {
const { default: mermaid } = await import('mermaid');
mermaid.initialize({ startOnLoad: false });
const { svg } = await mermaid.render('diagram-' + Date.now(), this.diagram);
this.container.nativeElement.innerHTML = svg;
}This keeps initial bundle size small and loads Mermaid on demand.
Common Issues and Fixes
"Cannot read properties of undefined (reading 'getElementById')"
Mermaid ran before the DOM was ready. Always call mermaid.render() inside ngAfterViewInit, not ngOnInit.
Diagram renders once but doesn't update
Implement ngOnChanges and call render() there. Also clear the container before re-render:
this.container.nativeElement.innerHTML = '';
const { svg } = await mermaid.render(id, this.diagram);SVG is tiny or invisible
Add CSS to the host element: display: block; width: 100%;
Alternative: Use MermaidEditor.lol for Rapid Prototyping
Before wiring diagrams into your Angular app, prototype them at mermaideditor.lol. The live editor gives instant preview, syntax highlighting, and one-click PNG/SVG export. Once your diagram looks right, paste the definition string into your Angular component.
Conclusion
Integrating Mermaid.js into Angular is straightforward with a standalone MermaidComponent. Key takeaways:
- Use ngAfterViewInit for initialization and ngOnChanges for updates.
- Guard Mermaid calls behind isPlatformBrowser for SSR apps.
- Lazy-load Mermaid to keep bundle size in check.
- Dynamic diagram strings from component state unlock powerful data-driven visuals.
Whether you're documenting API flows, state machines, or CI/CD pipelines, Mermaid.js gives Angular teams a text-first diagramming solution that lives right alongside your code.