MSDN Documentation

Core Web Development | .NET

JavaScript Interop in Blazor

This document covers how to call JavaScript functions from .NET code and .NET methods from JavaScript code in Blazor applications.

Understanding JS Interop

Blazor allows you to seamlessly integrate with existing JavaScript code. This is crucial for leveraging browser APIs, using third-party JavaScript libraries, or when you need to perform DOM manipulations that are more naturally handled in JavaScript.

Calling JavaScript from .NET

You can invoke JavaScript functions from your Blazor components using the IJSRuntime service. This service is available via dependency injection.

Example: Invoking a simple JavaScript function

First, ensure you have a JavaScript function defined in your wwwroot/index.html or an included JavaScript file:

function showMessage(message) {
    alert(message);
}

In your Blazor component (e.g., a .razor file), inject IJSRuntime and call the JavaScript function:

[Inject]
IJSRuntime JS { get; set; }

async Task CallJavaScript()
{
    await JS.InvokeVoidAsync("showMessage", "Hello from Blazor!");
}

The InvokeVoidAsync method is used when the JavaScript function doesn't return a value. If it returns a value, use InvokeAsync<T>, where T is the expected return type.

Example: Invoking a JavaScript function that returns a value

JavaScript function:

function addNumbers(a, b) {
    return a + b;
}

Blazor component:

[Inject]
IJSRuntime JS { get; set; }

async Task GetSum()
{
    int result = await JS.InvokeAsync<int>("addNumbers", 5, 7);
    Console.WriteLine($"The sum is: {result}"); // Output: The sum is: 12
}

Calling .NET Methods from JavaScript

To call .NET methods from JavaScript, you need to use the DotNetObjectReference. This creates a reference to a .NET object that can be passed to JavaScript.

Example: Creating a DotNetObjectReference

In your Blazor component:

@implements IDisposable

// ... other component code

private DotNetObjectReference<MyComponent> objRef;

protected override void OnInitialized()
{
    objRef = DotNetObjectReference.Create(this);
}

[JSInvokable]
public void SayHelloFromDotNet(string name)
{
    Console.WriteLine($"Hello, {name} from .NET!");
}

public void Dispose()
{
    objRef?.Dispose();
}

Now, you need to pass this reference to JavaScript. This is often done when initializing your JavaScript code or when calling a JavaScript function that expects the .NET object reference.

JavaScript code (e.g., in wwwroot/index.html or a script file):

// Assume 'componentReference' is passed from Blazor
// Example: window.myBlazorComponentRef = componentReference;

function callDotNetMethod(componentReference, name) {
    if (componentReference) {
        componentReference.invokeMethodAsync("SayHelloFromDotNet", name);
    }
}

In your Blazor component, you would invoke this JavaScript function:

[Inject]
IJSRuntime JS { get; set; }

async Task CallDotNetFromJs()
{
    // This assumes 'window.myBlazorComponentRef' is set in JS to the DotNetObjectReference
    await JS.InvokeVoidAsync("callDotNetMethod", objRef, "JavaScript");
}

Alternatively, you can pass the DotNetObjectReference directly when needed:

[Inject]
IJSRuntime JS { get; set; }

async Task CallDotNetDirectly()
{
    // This passes the reference directly to a JS function that expects it
    await JS.InvokeVoidAsync("someJavaScriptFunctionThatAcceptsDotNetRef", objRef);
}

Managing the Lifespan of DotNetObjectReference

It's crucial to dispose of DotNetObjectReference instances when they are no longer needed to prevent memory leaks. Implement the IDisposable interface in your component and call objRef?.Dispose() in the Dispose() method.

Common Use Cases

  • Integrating charting libraries (e.g., Chart.js, D3.js).
  • Using browser APIs like Geolocation or LocalStorage.
  • Implementing complex UI interactions not covered by Blazor's declarative model.
  • Calling legacy JavaScript code.

Performance Considerations

Excessive or synchronous JS Interop calls can impact performance. Consider batching calls where possible and minimizing the number of round trips between .NET and JavaScript.

Conclusion

JavaScript Interop is a powerful feature that extends the capabilities of Blazor. By understanding how to call between .NET and JavaScript, you can build rich and interactive web applications.