Skip to content

JavaScript Interop in Blazor

Calling JavaScript from .NET

Basic JavaScript Invocation

razor
@inject IJSRuntime JS

@code {
    private async Task ShowAlert()
    {
        await JS.InvokeVoidAsync("alert", "Hello from Blazor!");
    }

    private async Task<string> GetPromptResult()
    {
        return await JS.InvokeAsync<string>("prompt", "Enter your name:");
    }
}

Working with JavaScript Modules

javascript
// wwwroot/js/myModule.js
export function showAlert(message) {
    alert(message);
}

export function calculateTotal(items) {
    return items.reduce((sum, item) => sum + item.price, 0);
}
razor
@inject IJSRuntime JS
@implements IAsyncDisposable

@code {
    private IJSObjectReference? module;

    protected override async Task OnInitializedAsync()
    {
        module = await JS.InvokeAsync<IJSObjectReference>(
            "import", "./js/myModule.js");
    }

    private async Task ShowAlert()
    {
        if (module is not null)
        {
            await module.InvokeVoidAsync("showAlert", "Hello!");
        }
    }

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (module is not null)
        {
            await module.DisposeAsync();
        }
    }
}

Calling .NET from JavaScript

Static .NET Methods

csharp
public class ExampleJsInterop
{
    [JSInvokable]
    public static string GetHelloMessage()
    {
        return "Hello from .NET!";
    }

    [JSInvokable]
    public static Task<int> CalculateSquare(int number)
    {
        return Task.FromResult(number * number);
    }
}
javascript
// Call static .NET methods
await DotNet.invokeMethodAsync('YourAssemblyName', 'GetHelloMessage');
const result = await DotNet.invokeMethodAsync('YourAssemblyName', 'CalculateSquare', 5);

Instance Methods

razor
@inject IJSRuntime JS

<button @onclick="SetupJavaScriptCallback">Setup Callback</button>

@code {
    private async Task SetupJavaScriptCallback()
    {
        var dotNetHelper = DotNetObjectReference.Create(this);
        await JS.InvokeVoidAsync("setupCallback", dotNetHelper);
    }

    [JSInvokable]
    public void HandleCallback(string message)
    {
        Console.WriteLine($"Received: {message}");
    }
}
javascript
// JavaScript
window.setupCallback = (dotNetHelper) => {
    dotNetHelper.invokeMethodAsync('HandleCallback', 'Hello from JS!');
};

Working with DOM Elements

Element References

razor
<input @ref="inputElement" />
<button @onclick="FocusInput">Focus Input</button>

@code {
    private ElementReference inputElement;

    private async Task FocusInput()
    {
        await inputElement.FocusAsync();
    }
}

Custom JavaScript Functions

javascript
// wwwroot/js/utilities.js
window.utilities = {
    highlight: function (element) {
        element.style.backgroundColor = 'yellow';
    },
    
    getBoundingBox: function (element) {
        const rect = element.getBoundingClientRect();
        return {
            x: rect.x,
            y: rect.y,
            width: rect.width,
            height: rect.height
        };
    }
};
razor
@inject IJSRuntime JS

<div @ref="divElement">Content to highlight</div>
<button @onclick="HighlightDiv">Highlight</button>

@code {
    private ElementReference divElement;

    private async Task HighlightDiv()
    {
        await JS.InvokeVoidAsync("utilities.highlight", divElement);
    }
}

Error Handling

razor
@inject IJSRuntime JS

@code {
    private async Task TryJavaScript()
    {
        try
        {
            await JS.InvokeAsync<object>("nonExistentFunction");
        }
        catch (JSException ex)
        {
            Console.WriteLine($"JavaScript error: {ex.Message}");
        }
    }
}

Best Practices

  1. Module Pattern: Use JavaScript modules for better organization and scoping.
  2. Dispose Resources: Always dispose of JavaScript module references.
  3. Error Handling: Implement proper error handling for JavaScript interop calls.
  4. Performance: Minimize JavaScript interop calls as they can impact performance.
  5. Type Safety: Use TypeScript for better type safety when working with JavaScript.