Learn how YOU can use both C# and JavaScript in your Blazor app with the JavaScript interop 
Tags: dotnet, tutorial, webdev, javascript
Published: 2019-11-09 00:31:50

---
title: Learn how YOU can use both C# and JavaScript in your Blazor app with the JavaScript interop 
published: true
description: Learn how to call JavaScript code from C# and your Blazor Component
tags: dotnet, tutorial, webdev, javascript
cover_image: https://thepracticaldev.s3.amazonaws.com/i/knm2cc39ujgar21wzmsa.jpg
series: blazor
---

Follow me on [Twitter](https://twitter.com/chris_noring), happy to take your suggestions on topics or improvements /Chris

> Blazor is the new framework from Microsoft that will make it possible to build applications for the Web using nothing but C#. It's easy at first look to think - Great I don't need to learn JavaScript. To be honest, I think this is the wrong way to look at it. Having a huge ecosystem of libraries written in JavaScript is an opportunity. At the end of the day, it's about solving the client's problem and doing so in a fast and efficient way. With Blazor we know have the opportunity to use the best of two worlds. The .NET Apis and the JavaScript ecosystem. 

TLDR; This article will show how to use something called the JavaScript interop which allows us to call JavaScript code from Blazor. Learn to be the developer that leverages two powerful ecosystems .NET APIs and the JavaScript ecosystem.

In this article, we assume that you as a reader knows what Blazor is. It's recommended that if you are completely new to Blazor you first have a read through this introductory article:
{% link https://dev.to/dotnet/blazor-the-future-of-net-web-apps-a-first-look-m8 %}

## References

- [JavaScript and Blazor doc](https://docs.microsoft.com/aspnet/core/blazor/javascript-interop?view=aspnetcore-3.0?wt.mc_id=devto-blog-chnoring)
This link describes everything this article has gone through but also covers how you would from JavaScript call your Blazor component and additionally it talks about lifecycles

- [Introduction to Blazor doc](https://docs.microsoft.com/aspnet/core/blazor/?view=aspnetcore-3.0?wt.mc_id=devto-blog-chnoring)
This is a good introduction page to Blazor

- [Introduction to Razor templating with Blazor](https://docs.microsoft.com/aspnet/core/mvc/views/razor?view=aspnetcore-3.0?wt.mc_id=devto-blog-chnoring)
New to Razor templating and especially what tags exist in Blazor? Then this page is for you

- [Part one on Blazor, start here if you don't know anything about Blazor](https://docs.microsoft.com/aspnet/core/host-and-deploy/?view=aspnetcore-3.0?wt.mc_id=devto-blog-chnoring)
Want to know how to deploy your Blazor app? This goes through both a server hosted Blazor app as well as a WebAssembly version

## WHY

As we mentioned at the beginning of this article. In my opinion, it's not good to limit ourselves to only use the .NET APIs. At the end of the day, it's about getting the job done. For that reason learning how to execute JavaScript from within Blazor is a skill worth having, especially if it means that we can leverage other existing libraries from for example NPM. Another reason for wanting to execute JavaScript from within Blazor might be that we need to use a specific Browser capability. 

## WHAT

This article covers something called the JavaScript interop. At our disposal, we have an abstraction called `IJSRuntime` and on it, we execute the method `InvokeAsync<T>()`. The method expects the name of the function you want to execute and a list of serialized JSON parameters. A typical call looks something like this:

```csharp
var result = await JSRuntime.InvokeAsync<string>("methodName", input);
```

What happens in the above code is that the method `methodName()` is being invoked and the parameter `input` is being turned into a string. 

### Different ways to use the `IJSRuntime`

You can call the JavaScript interop from different places. Either:
- **From the component**, If you want to use it from within a component you just need an inject statement at the top of the component like so: 

```
@inject IJSRuntime JSRuntime
```

- **From the a C# class**, if you want to use the interop from within a class you need to inject it into the class's constructor like so: 

```csharp
class Something 
{
  Something(IJSRuntime jsRuntime) 
  {

  }
}
```

## DEMO

Ok, so what are we building? Well, let's do the following:

- **Scaffold** a project, we need to create a Blazor project. We can do that from the command line 
- **Invoke** javascript functions, we will create a Blazor component where we will add some code to showcase different ways of calling the JavaScript code using the interop functionality.
- **Download** and use a library from NPM, we will leverage the NPM ecosystem by downloading an NPM library and call that from our Blazor Component 

### Scaffold a project

As Blazor is constantly updated, ensure you are looking at the latest instructions for installing it:

> https://docs.microsoft.com/en-us/aspnet/core/blazor/get-started?view=aspnetcore-3.1&tabs=visual-studio


There are two things that needs to be installed for us to be able to create a Blazor project:

1. Blazor templates, we can easily install these from the command line with the command 
2. .NET Core, latest and greatest

You need to download .Net Core 3.0. Check out this link to find the correct distribution for your OS

> https://dotnet.microsoft.com/download/dotnet-core/3.0

You want to be picking the latest and greatest on the above page cause it will give you the latest features of Blazor and usually Blazor templates rely on the latest possible version of .NET Core.

Additionally, you need templates so you can scaffold a Blazor app. Pop open a terminal and type

```
dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.1.0-preview2.19528.8
```

### Invoke JavaScript functions

So the first question is, of course, how can we be calling JavaScript functions and with what? We know the first part of the answer. We should be using `IJSRuntime` and the method `InvokeAsync()`. Next, we need to know where to place our JavaScript? 

The answer is inside of a script file and we need to refer to this script file by placing a `script` tag in the directory `wwwwroot` and the file `index.html`.

```
-| wwwroot/
---| index.html
```

Let's say then that we create a file `library.js` in `wwwroot` so we know have:

```
-| wwwroot/
---| index.html
---| library.js
```

Then we need to open up `index.html` and add our script tag like so:

```html
<!-- index.html -->
<script src="library.js"></script>
```

What about the content of `library.js` then? Well here it is:

```js
// library.js

function add(lhs, rhs) {
  return lhs+rhs;
}
```

At this point, let's go to our `Pages` directory and create a new component `Jsdemo.razor`, like so:

```
-| Pages
---| Jsdemo.razor
```

give it the following content:

```csharp
@page "/jsdemo"
@inject IJSRuntime JSRuntime

<h2>JS Demo</h2>
Result : @result

<button @onclick="Add">Add</button>

@code {
  int result = 0;

  public async void Add() 
  {
    result = await JSRuntime.InvokeAsync<int>("add",1,2);
  }
}
```

There are many things that go on here:

1. We call `JSRuntime.InvokeAsync<int>("add",1,2)`, with the first arg being `add`, the name of the function. Followed by `1,2`, which are the arguments to the function. 
2. Then we notice `<int>`, this sets up the return type of the function
3. Looking at the full function: 

```js
public async void Add() 
{
  result = await JSRuntime.InvokeAsync<int>("add",1,2);
}
```

we see that we call `await` to wait for the response, which also means we need to mark our `Add()` function with `async` to make the compiler happy. 

### An example with more complex parameters

Ok, we want to ensure that it still works by invoking functions with parameters that are arrays and even objects.

Let's add two functions to our `library.js` and update it's content to the following:

```js
// library.js

function add(lhs, rhs) {
  return lhs+rhs;
}

function commonElements(arr1, arr2) {
  return arr1.filter(a => arr2.find(b => b === a)).join(',');
}
```

So how to call it? Well, just like we did before using `JSRuntime.InvokeAsync<int>("name-of-method",arg...)`.

Let's go update our Blazor component `Jsdemo.razor` to this:

```csharp
@page "/jsdemo"
@inject IJSRuntime JSRuntime

<h2>JS Demo</h2>
Result : @result

Common elements result:
@stringResult

<button @onclick="Add">Add</button>
<button @onclick="Common">Common elements</button>

@code {
  int result = 0;
  string stringResult = "";
  int[] arr1 = new int [2]{1,2};
  int[] arr2 = new int [2]{2,3};

  public async Common() 
  {
    stringResult = await JSRuntime.InvokeAsync<string>("commonElements",arr1,arr2);
  }

  public async void Add() 
  {
    result = await JSRuntime.InvokeAsync<int>("add",1,2);
  }
}
```

Note above how we add some markup for this new result:

```csharp
Common elements result:
@stringResult

<button @onclick="Common">Common elements</button>
```

We also need to create some new input parameters, two arrays:

```csharp
int[] arr1 = new int [2]{1,2};
int[] arr2 = new int [2]{2,3};
```

Lastly we add the method `Common()`, like so:

```csharp
public async Common() 
  {
    stringResult = await JSRuntime.InvokeAsync<int>("commonElements",1,2);
  }
```

As you can see there is really no difference between having primitives our arrays as inputs. The main reason is that everything gets serialized to JSON on the .NET side and is de-serialized right back when the JavaScript function is being invoked.

### Calling NPM code

Ok, so let's talk about using JavaScript libraries. After all one of the strengths of Blazor lies in the ability to use both ecosystems, both .NET and NPM. So how do we do that?

Well, we need to consider the following:

1. Large libraries, some libraries are really big out there, like `Lodash`. Fortunately, there is a way to import only the functions we are going to need, the rest can be omitted through a process called *tree shaking*
2. If we are using only a part of a library like the above scenario we need a way to extract the code we need, so we need a tool like `browserify` or `webpack` to create a bundle of a subset of code

Ok then, we understand what we need to consider. Now let's do just that, let's extract a function from the library `lodash`. Let's list the steps we need to take:

- **Create** a directory where our bundle and downloaded libraries will live
- **Download** the NPM library
- **Set up** up a tool like `browserify` to make it possible to create bundle with an `NPM command`
- **Create** the bundle with `browserify` and include the resulting bundle as a script tag
- **Try out** code from our bundle

**Create**

Let's create a directory under `wwwroot` called `npm-libs`, you can call it what you want.

It should now looks like this:

```
-| wwwroot
---| npm-libs/
```

We will treat this is as a Node.js project and with Node.js projects you want to initialize it using `npm init`, like so:

```
npm init -y 
```

This will give us a nice Node.js project with some good defaults and most of all a `package.json` file. 

```
-| wwwroot
---| npm-libs/
------| package.json 
```


We will use this `package.json` file as a manifest file that tells us about the libraries we need and commands we can use to build our bundle. 

**Download**

Inside of our `npm-libs` we now run the `npm install` command to give us the library we want, in this case, `lodash`:

```
npm install lodash
```

This means that our file structure now contains a `node_modules` directory, with our downloaded library, like so:

```
-| wwwroot
---| npm-libs/
------| package.json 
------| node_modules/
```

**Set up**

Next, we need to install our bundling tool `browserify`:

```
npm install -g browserify
```

We are now ready to define a command to run `browserify`,it should look like so:

```
browserify -d index.js > bundle.js
```

The above will take the file `index.js`, walk the tree over all its dependencies and produce a bundle, that we call `bundle.js`. Note also how we include `-d`, this is for source maps. Source maps mean our modules will be remembered for how they looked prior to *bundling*. We should lose the `-d` when in production because the source maps makes the bundle bigger. 

Let's put this command in the `scripts` section of `package.json` so we now have:

```json
"build": "browserify -d index.js > bundle.js"
```

Ok then, the next step is to create our `index.js` like so:

```
-| wwwroot
---| npm-libs/
------| index.js
------| package.json 
------| node_modules/
```

and give it the following content:

```js
// index.js

var intersect = require('lodash/fp/intersection');

window.intersect = function(arg1, arg2) {
  let result = intersect(arg1, arg2);
  return result.join(',');
};
```

What we are doing above is asking for a subset of `lodash` by only loading the function `intersection`:

```js
var intersect = require('lodash/fp/intersection');
```

this means that when this *tree-shakes*, it will only include the `intersection` code and our bundle will be at a minimum.

Next, we assign the `intersection` function to the `window` property and expose it so our C# code can call it.

```js
window.intersect = function(arg1, arg2) {
  let result = intersect(arg1, arg2);
  return result.join(',');
};
```

At this point we run:

```
npm run build
```

This should produce a `bundle.js`. We should also add a reference to our `bundle.js` in our `index.html` file, like so:

```html
<script src="bundle.js"></script>
```

**Try it out**

Lastly, we want to call this JavaScript code from our Blazor component. So we add the following code to our `@code` section, like so:

```csharp
 public async void Intersect() 
  {
     intersectResult = await JSRuntime.InvokeAsync<string>("intersect",arr1, arr2);
     Console.WriteLine(intersectResult);
  }
```

and the following to our markup:

```html
<button @onclick="Intersect">Intersect</button>

Intersect:
@intersectResult
```

## Full code of our Blazor component

Let's show the full code in case you got lost somewhere:

```csharp
@page "/jsdemo"
@inject IJSRuntime JSRuntime

<h2>JS Demo</h2>
Result : @result

<button @onclick="Click">Press</button>
<button @onclick="Add">Add</button>
<button @onclick="Intersect">Intersect</button>

Intersect:
@intersectResult

@code {
  int result = 0;
  string intersectResult = "replace me";
  
  int[] arr1 = new int [2]{1,2};
  int[] arr2 = new int [2]{2,3};

  public async void Intersect() 
  {
     intersectResult = await JSRuntime.InvokeAsync<string>("intersect",arr1, arr2);
     Console.WriteLine(intersectResult);
  }

  public async void Add() 
  {
    result = await JSRuntime.InvokeAsync<int>("add",1,2);
  }

  void Click() 
  {
    JSRuntime.InvokeAsync<string>("alert","hello");
  }
}
```

## Summary

And that's all, that's what we wanted to achieve. We tried out different ways of calling our code, with primitive parameters, without it. We even showed how we could download a JavaScript library from NPM and make that part of our project. 

I hope this was educational and that you are helped for the following scenarios:

- **Occasional usage**, Calling JavaScript code occasionally
- **Leveraging existing libraries**, you might have existing libraries you've written and don't want to reinvent the wheel or maybe there's a library on NPM that just does what you want it to.