Blazor and the JavaScript interop.

In the post Logging in Blazor we saw how we can use the IJSRuntime to call out to the JavaScript runtime.

Ofcourse we can interop with any JavaScript code within our application, so for example let’s make some simple changes to the index.html from that post and add a script block, such as this

<script>
   function displayMessage(msg) {
      alert(msg);
   }
</script>

Nothing very special here, but we just want something visual to more easily see our interop calls.

Next, in our .razor file let’s simple add a button and associated code block

<button @onclick="DisplayMessage">Alert</button>

@code {
   private void DisplayMessage()
   {
      JsRuntime.InvokeVoidAsync("displayMessage", "Hello JavaScript World");
   }
}

The IJSRuntime interface has the following methods

public interface IJSRuntime
{
   ValueTask<TValue> InvokeAsync<TValue>(string identifier, 
      object[] args);
   ValueTask<TValue> InvokeAsync<TValue>(string identifier, 
      CancellationToken cancellationToken, object[] args);
}

As you can see, both return a ValueTask, hence are awaitable, but neither matches our InvokeVoidAsync method. This is because there are a bunch of extension methods within JSRuntimeExtensions. These extension methods check that the supplied IJSRuntime is not null and then calls the interface methods.

In the example above, we are not interested in the return value, so let’s now return some value from our JavaScript…

Change the script to

<script>
   function displayMessage(msg) {
      return prompt(msg);
   }
</script>

and now change the C# code in our code block to

private async void DisplayMessage()
{
   Debug.WriteLine(
      await JsRuntime.InvokeAsync<string>(
         "displayMessage", "Hello JavaScript World"
      )
   );
}

At this point, we’re receiving the return from our JavaScript function and (in the case of a WebAssembly application) outputting to the browser console.

Ofcourse we can now write JavaScript code and call this from Blazor as well.