About JavaScript Location
Load a script in the <head> tag
<head>
<script src="js/first.js"></script>
<script>
window.jsMethod = (methodParameter) => {
...
};
</script>
</head>
Load a script in the <body> tag
<body>
<script src="js/first.js"></script>
<script>
window.jsMethod = (methodParameter) => {
...
};
</script>
</body>
Colocate with the component
Component: CountComponent.razor
Component: CountComponent.razor.cs
Style: CountComponent.razor.css
Script: CountComponent.razor.js
Call JS from .NET
Create an app.js file under wwwroot
function helloWorld() {
alert('Hello World');
}
function add(a, b) {
return a + b;
}
Include the JS file in App.razor
Script inclusion in the current web project
<head>
<script src="@Assets["app.js"]"></script>
</head>
If an RCL component library is used
<head>
<script src="_content/LibraryName/app.js"></script>
</head>
Call JS methods from a .NET component
@inject IJSRuntime JS
<button class="btn btn-primary" @onclick="SayHello">SayHello</button>
<button class="btn btn-primary" @onclick="Add">Add</button>
<p>Current count: @result</p>
@code {
private int result = 0;
private async Task SayHello()
{
await JS.InvokeVoidAsync("helloWorld");
}
private async Task Add()
{
result = await JS.InvokeAsync<int>("add", result, 1);
StateHasChanged();
}
}
Module-based JS files
export function helloWorld() {
alert('Hello World');
}
export function add(a, b) {
return a + b;
}
Write the following code in the MyComponent.razor component
@inject IJSRuntime JS
@implements IAsyncDisposable
@code {
private IJSInProcessObjectReference? module;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var jsInProcess = (IJSInProcessRuntime)JS;
module = await JS.InvokeAsync<IJSInProcessObjectReference>("import", "./path/to/MyComponent.razor.js");
var value = module.Invoke<string>("javascriptFunctionIdentifier");
}
}
async ValueTask IAsyncDisposable.DisposeAsync()
{
try
{
if (module is not null)
{
await module.DisposeAsync();
}
}
catch (JSDisconnectedException)
{
}
}
}
<div @ref="divElement" style="margin-top:2000px">
Set value via JS interop call: <strong>@scrollPosition</strong>
</div>
@code {
private ElementReference divElement;
private int scrollPosition;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var jsInProcess = (IJSInProcessRuntime)JS;
var module = await jsInProcess.InvokeAsync<IJSInProcessObjectReference>("import", "./path/to/MyComponent.razor.js");
scrollPosition = await module.InvokeAsync<int>("getScrollPosition", divElement);
}
}
}
Two static methods are provided
DotNet.invokeMethodAsync('{ASSEMBLY NAME}', '{.NET METHOD ID}', {ARGUMENTS});
DotNet.invokeMethod('{ASSEMBLY NAME}', '{.NET METHOD ID}', {ARGUMENTS});
Provide a static method in the C# component
@code {
[JSInvokable]
public static Task{<T>} {.NET METHOD ID}()
{
...
}
}
You can specify a parameter to change the method name
[JSInvokable("DifferentMethodName")]
public static Task{<T>} {.NET METHOD ID}()
{
...
}
Call .NET methods via dotNetHelper
A .NET instance is passed to JS by reference by wrapping it in a DotNetObjectReference and calling Create on it.
@inject IJSRuntime JS
@implements IAsyncDisposable
@code {
private DotNetObjectReference<MyComponent>? dotNetHelper;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
dotNetHelper = DotNetObjectReference.Create(this);
await JS.InvokeVoidAsync("jsFunction", dotNetHelper);
}
}
public async ValueTask DisposeAsync()
{
if (dotNetHelper is not null)
{
await dotNetHelper.DisposeAsync();
}
}
}