angularmermaid

How to properly use MermaidJS in Angular?


I was going to use mermaid in Angular by installing the module with npm i -D mermaid and test with one of the examples of the docs, ok but it does not work. Seems like a frequent problem.

I tried the following code with and without calling the JS API through .

<pre class="mermaid">
    graph TD
    A[Client] --> B[Load Balancer]
    B --> C[Server01]
    B --> D[Server02]

    journey
    title My working day
    section Go to work
      Make tea: 5: Me
      Go upstairs: 3: Me
      Do work: 1: Me, Cat
    section Go home
      Go downstairs: 5: Me
      Sit down: 5: Me
</pre>

<script type="module">
  import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
  mermaid.initialize({ startOnLoad: true });
</script>

output

I tried using this solution but it doesnt work too. (Property 'mermaid' has no initializer and is not definitely assigned in the constructor & Property 'initialize' does not exist on type 'typeof ).

Thanks.


Solution

  • The modern but in developer preview way

    You can import the library and initialize it after Angular has finished rendering the template in the browser. To do so, you can use the afterNextRender API. Beware that the API is still in developer preview, so it's not stable yet

    import { afterNextRender, Component } from "@angular/core";
    import mermaid from "mermaid";
    
    @Component({
     // ...
    })
    export class MermaidComponent {
      constructor() {
        afterNextRender({
          read: () => {
            void mermaid.init()
          }
        })
      }
    }
    

    The void before mermaid.init can actually be removed. It's just to ignore the linter warning about not waiting for .init promise

    This way Angular will wait until the template is there so Mermaid can be initialized when HTML elements are there.

    By using this API, the initialization code only runs on the browser. Which is useful as mermaid doesn't support server side rendering (yet?)

    Stable way

    If you want to use something stable to check if the app is running in a browser or not to perform the initialization, you can also use:

    import { AfterViewInit, Component, Inject, PLATFORM_ID } from "@angular/core";
    import { isPlatformBrowser } from "@angular/common";
    import mermaid from "mermaid";
    
    @Component({
      // ...
    })
    export class MermaidComponent implements AfterViewInit {
      constructor(@Inject(PLATFORM_ID) private _platformId: object) {
      }
    
      ngAfterViewInit(): void {
        if (isPlatformBrowser(this._platformId)) {
          void mermaid.init()
        }
      }
    }
    

    If you're sure you won't ever run your app with server side rendering (SSR) or pre-rendering (SSG) you could actually skip the if clause regarding where the code runs on the browser. But just in case it's a good practice to think about it just in case you want to add that later to your project

    Example app

    Created also an example Angular v18 app using mermaid in case you want to take a look. The important piece is the MermaidComponent.

    The second alternative code is in the classic-way branch