• Blazor
  • ASP.NET Core
  • .NET
  • C#

Blazor Dynamic JavaScript Runner

Even with Blazor you still need to use javascript in some form or fashion. And with this post we will go over how to create a simple JavaScript runner. The runner will just take a method identifier, the script as a string, and some arguments in the form of a simple object in C#.

The Need

The main need for my personal work was to be able to focus an element on the page with very minimal code, not having to craft a whole interop between the C# and JavaScript code. The output was a simple JavaScript function that will be called by a simple abstraction in C#. With Blazor having a way to pass a reference to an element on the page thorough the JS Interop functionality this make is really easy to just focus the element using a short string script.

Project Example

Below is an example Component and the the necessary interop files.

Here is project: EventHorizon.Blazor.Scripter

Samples.razor


<button @onclick="HandleAlertUser">Show Alert</button>
<br />
<button @onclick="HandlePromptUser">Prompt User</button>

@code {
    // Make sure to Register JavaScriptRunner with DI
    [Inject]
    public JavaScriptRunner JSRunner { get; set; }

    public async Task HandlePromptUser()
    {
        // Close the window with JavaScript.
        await JSRunner.Run(
            "closeWindow",
            "var name = prompt('What is your name?'); if(name) alert(name);",
            new { }
        );
    }

    public async Task HandleAlertUser()
    {
        // Say Hello to the UserName
        await JSRunner.Run(
            "alertUser",
            // To note that passed props will be converted to camel-case
            "alert('Hello, ' + $args.userName)",
            new
            {
                UserName = "Awesome",
            }
        );
    }
}

JavaScriptRunner.cs

public class JavaScriptInteropRunner : JavaScriptRunner
{
    readonly IJSRuntime _runtime;

    public JavaScriptInteropRunner(
        IJSRuntime runtime
    )
    {
        _runtime = runtime;
    }

    public ValueTask Run(
        string methodName,
        string script,
        object args
    )
    {
        return _runtime.InvokeVoidAsync(
            "scripter.runScript",
            new JavaScriptMethodRunner
            {
                MethodName = methodName,
                Script = script,
                Args = args
            }
        );
    }
}

public class JavaScriptMethodRunner
{
    public string MethodName { get; set; }
    public string Script { get; set; }
    public object Args { get; set; }
}

scripter.js

// This file is to show how a library package may provide JavaScript interop features
// wrapped in a .NET API

((_window) => {
    const methodCache = {};

    _window.scripter = {
        runScript: (methodRunner) => {
            methodCache[methodRunner.methodName] = new Function(
                "$args",
                methodRunner.script
            );
            methodCache[methodRunner.methodName](methodRunner.args);
        },
    };

})(window);
Cody's logo image, it is an abstract of a black hole with a white Event Horizon.

Cody Merritt Anhorn

A Engineer with a passion for Platform Architecture and Tool Development.