Render Mermaid diagram with Blazor WebAssembly App in .NET 5.0

2.8k Views Asked by At

I have followed the guide for Deploying Mermaid here:

https://mermaid-js.github.io/mermaid/#/?id=deploying-mermaid

Using it on codepen works directly:

https://codepen.io/Ogglas/pen/MWjWNxR

mermaid.initialize({
  startOnLoad:true
});

<div class="mermaid">
    graph LR
        A[Client] --- B[Load Balancer]
        B-->C[Server01]
        B-->D(Server02)
</div>

To enable it in Blazor i edited BlazorApp.Client -> wwwroot -> index.html and added the following below <script src="_framework/blazor.webassembly.js"></script>.

<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>mermaid.initialize({startOnLoad:true});</script>

I then edited Index.razor with the following values:

<h1>Hello, world!</h1>

Welcome to your new app.

<div class="mermaid">
    graph LR
        A[Client] --- B[Load Balancer]
        B-->C[Server01]
        B-->D(Server02)
</div>

However this does not render the mermaid diagram. What am I doing wrong?

3

There are 3 best solutions below

0
On BEST ANSWER

Solved it with a button click for now:

Index.razor:

@page "/"
@inject IJSRuntime JSRuntime

<h1>Hello, world!</h1>

Welcome to your new app.

<div>
    <button @onclick="TriggerClick">
        Trigger Mermaid diagram render
    </button>
</div>

<div>
    Graph:
    <div id="output"></div>
</div>

<SurveyPrompt Title="How is Blazor working for you?" />

@code {

    public async Task TriggerClick()
    {
        await JSRuntime.InvokeVoidAsync("renderMermaidDiagram");
    }
}

index.html, add this to the <head> section:

<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>
    window.renderMermaidDiagram = () => {
        var output = document.getElementById("output");
        var input = "graph LR \n" +
            "A[Client] --- B[Load Balancer] \n" +
            "B-->C[Server01] \n" +
            "B-->D(Server02) \n";
        mermaid.mermaidAPI.render('theGraph', input, function (svgCode) {
            output.innerHTML = svgCode;
        });
    }
</script>

Will look like this:

enter image description here

Note that some of the tutorials for mermaid uses outdated versions and will not work with the latest releases.

Sources:

https://mermaid-js.github.io/mermaid/#/Tutorials?id=mermaid-with-html

https://learn.microsoft.com/en-us/aspnet/core/blazor/call-javascript-from-dotnet?view=aspnetcore-5.0

0
On

Mermaid (8.11.5 used for testing) + Blazor server-side solution (this has not been tested with client-side):

I put JS inter-op in its own object and file, e.g. blazor-helper.js:

var JsFunctions = window.JsFunctions || {};
JsFunctions = {
    MermaidInitialize: function() {
        mermaid.initialize({
            startOnLoad: true,
            securityLevel: "loose",
            // Other options.
          });
    },

    MermaidRender: function() {
        mermaid.init();
    }
};

Obviously, one could get away without abstracting mermaid.init(), but I think it provides clarity.

Then in your blazor code (c#9 syntax with nullable enabled):

    [Inject]
    protected IJSRuntime? JsRuntime { get; set; } = null;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if(this.JsRuntime is not null)
        {
            if(firstRender)
            {
                await this.JsRuntime.InvokeVoidAsync("JsFunctions.MermaidInitialize");
            }

            await this.JsRuntime.InvokeVoidAsync("JsFunctions.MermaidRender");
        }
    }
1
On

For serverside i have some rendering problems as well. (still investigating why so i can fix this)

Current situation for serverside:

Add this part of html in your page with reference to js file from mermaid.

<div class="mermaid">
   graph LR
   A[Client] --- B[Load Balancer]
   B-->C[Server01]
   B-->D(Server02)
</div>

This renders normal in pre-rendering part, but the second part when the app bootstraps it's plain text again.

You can test this by adding this in the "@code" section of the page

protected override async Task OnInitializedAsync()
{
   string t = "Set breakpoint on this line, this will be hit 2 times";
}

The strange part is if you add or not "the part to initialze mermaid" i get the same behavior result.

mermaid.initialize({
        startOnLoad: true
    });

Clienside

I found this clientside nuget solution that works smooth

https://github.com/TrueCommerce/MermaidJS.Blazor