Appearance
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
- Module Pattern: Use JavaScript modules for better organization and scoping.
- Dispose Resources: Always dispose of JavaScript module references.
- Error Handling: Implement proper error handling for JavaScript interop calls.
- Performance: Minimize JavaScript interop calls as they can impact performance.
- Type Safety: Use TypeScript for better type safety when working with JavaScript.