Dynamically add JavaScript from Blazor components

Blazor Background

In this new post, I show you the code to dynamically add JavaScript from Blazor components. For example, I’m creating a new component to display a world map. Based on the configuration, the component shows different maps: for example, the world map or the USA. So, every map is in a JavaScript file. I don’t want to force me as a developer to add the correct JavaScript; I want that the component does it for me.

For this reason, I have to find a way to dynamically add JavaScript file from the Blazor component based on the configuration.

Blazor allows adding script tags only to the root HTML document. This makes it difficult to add JavaScript files that are required only in a single or few components.

Add Script to components

So, to load a script file in a component, we should first, add a JavaScript function that loads the JavaScript from the specified URL to the main JavaScript file of the project.

Create a script loader

Now, create a new JavaScript file script.js. Then, add a new function that will load a script file from the specified URL.

function loadJs(sourceUrl) {
	if (sourceUrl.Length == 0) {
		console.error("Invalid source URL");
		return;
	}

	var tag = document.createElement('script');
	tag.src = sourceUrl;
	tag.type = "text/javascript";

	tag.onload = function () {
		console.log("Script loaded successfully");
	}

	tag.onerror = function () {
		console.error("Failed to load script");
	}

	document.body.appendChild(tag);
}

Add this script file to the root document _Host.cshtml or Index.html. This file will be located in the Shared folder.

<script src="/js/script.js"></script>
<script src="_framework/blazor.server.js"></script>

Inject IJSRuntime

Now, go to the Index.razor component, or any other component where you want to load scripts dynamically inject the IJSRuntime.

@inject IJSRuntime _js

Then, override the OnAfterRenderAsync method and call the loadJs function.

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    var targetUrl = "/_content/yourcomponent/myjs.min.js";
    await _js.InvokeVoidAsync("loadJs", targetUrl);
}

In this example, we are loading a script from the component itself. Generally speaking, you can replace this URL with the URL to your JavaScript code.

Invoke JS Using IJSRuntime

Now, we have loaded a new script file dynamically from the component. Any function from the newly added script can be called with the help of IJSRuntime.

@page "/"
@inject IJSRuntime _js;

<h1>Hello, world!</h1>

Welcome to your new app.

<button @onclick="Alert">Show Alert</button>

@code{
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        var targetUrl = "https://unpkg.com/sweetalert/dist/sweetalert.min.js";
        await _js.InvokeVoidAsync("loadJs", targetUrl);

    }

    async Task Alert()
    {
        await _js.InvokeVoidAsync("swal", "Success!", "Script loaded", "success");
    }
}

I hope this post will help you. Happy coding. If you have any questions, let me know in the comments below.

Add a CSS

So, we saw how to dynamically add JavaScript from Blazor components. I can extend this code to add CSS to the page from Blazor components. This is the script.

function loadCSS(sourceUrl) {
	if (sourceUrl.Length == 0) {
		console.error("Invalid source URL");
		return;
	}

	var link = document.createElement('link');
	link.rel = "stylesheet";
	link.type = "text/css";
	link.href = sourceUrl;

	link.onload = function () {
		console.log("CSS loaded successfully");
	}

	link.onerror = function () {
		console.error("CSS to load script");
	}

	document.head.appendChild(link);
}

More examples and documentation

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.