In a Blazor application, you can call JavaScript
functions from C# (.NET) methods and C# (.NET) methods from JavaScript
functions. This is referred to as “JavaScript interoperability”
or “JS interop.” The JS interop allows you to integrate JavaScript
libraries into your Blazor application, and its primary function is to handle
DOM manipulation and browser API calls.
Please refer to this link to
learn more about JS interop in Blazor.
Please refer to this link for
calling and implementing JS interop in Blazor.
Using JavaScript onmousemove and onkeypress events to trigger the Timer function in a Razor component can identify whether a user is active or inactive. If the user has not performed any onmousemove or onkeypress events, the user is considered in an inactive state and the Timer function is called after certain TimeInterval to log the user out.
Follow these steps to log the user out automatically if they’re not active:
Call the onmousemove and onkeypress properties in a JavaScript function to fire the Timer function in the Razor component. [_Host.cshtml] <body> // . . . <script> function timeOutCall(dotnethelper) { document.onmousemove = resetTimeDelay; document.onkeypress = resetTimeDelay;
function resetTimeDelay() { dotnethelper.invokeMethodAsync("TimerInterval"); } } </script> </body>
Now call the Timer method to identify whether the user is active or not. Add navigation to the logout action when the user is inactive. [MainLayout.razor] @using System.Timers @inject NavigationManager UriHelper @inject IJSRuntime JSRuntime
protected override async Task OnInitializedAsync() { // Set the Timer delay. timerObj = new Timer(7000); timerObj.Elapsed += UpdateTimer; timerObj.AutoReset = false; // Identify whether the user is active or inactive using onmousemove and onkeypress in JS function. await JSRuntime.InvokeVoidAsync("timeOutCall", DotNetObjectReference.Create(this)); }
[JSInvokable] public void TimerInterval() { // Resetting the Timer if the user in active state. timerObj.Stop(); // Call the TimeInterval to logout when the user is inactive. timerObj.Start(); }
private void UpdateTimer(Object source, ElapsedEventArgs e) { InvokeAsync(async() => { // Log out when the user is inactive. var authstate = await stateAuthenticate; if (authstate.User.Identity.IsAuthenticated) { UriHelper.NavigateTo("logout", true); } }); } }
To get a browser’s culture in Blazor WebAssembly, call the (navigator.language) property in JavaScript using the JavaScript interop function in Blazor. It will return the current browser’s language version.
Follow this code to get the browser’s culture in Blazor WebAssembly.
To convert the date and time to a client’s or user’s time zone in Blazor Server, use the JavaScript function to get the current offset time difference from UTC in minutes using the new Date().getTimezoneOffset() method in Blazor using JavaScript Interop. Display the local time by the current offset time difference. Follow these steps to convert the server time zone to the user’s time zone.
Add the JavaScript function using JS Interop. Get the current offset time from UTC in minutes using the new Date().getTimezoneOffset() method. [_Host.razor]
<body> @*Requires render-server mode as "Server" while initializing the component to execute JavaScript in OnInitializedAsync.*@ <componenttype="typeof(App)" render-mode="Server" /> . . . . . .
<script> function GetTimezoneValue() { // Returns the time difference in minutes between UTC time and local time. return new Date().getTimezoneOffset(); } </script> </body >
Now display the UTC time and calculate the user time by using the offset time difference. [Index.razor]
To get the current data and time from client, use
the date object (new Date()) in JavaScript
using JavaScript Interop. It will return the browser’s date
and time. Following is the code to get the current date and time from the
client in Blazor WebAssembly.
<body>
. . .
. . .
<script>
function GetDateTime() {
// Date object will return browser's date and time by default in JavaScript.
document.getElementById("date-time").innerHTML = new Date();
}
</script>
</body >
Google reCaptcha is a process that helps to protect websites form spam and abuse. To implement Google reCaptcha in Blazor, refer to the Google reCaptcha script link the WebAssembly app and render the reCaptcha by calling the JavaScript function. Follow these steps to implement Google reCaptcha in Blazor WebAssembly.
Add the Google reCaptcha renderer function in a separate JavaScript file under the wwwroot folder. [googlereCaptcha.js]
Now call the rendering reCaptcha function in JavaScript from the Razor page using JavaScript Interop and show the reCaptcha response on button click. Note: To start using reCaptcha, you need to generate the API site key for your site. Refer to this link to generate the site key. [Index.razor]
Close a browser window from a page in Blazor WebAssembly using
JavaScript Interop with the window.close() method. The window.close() method closes the currently opened window.
In the following example, open a new browser window and
close it using the window.close() method with a button onclick event.
Window dimension values are read using JavaScript Interop with the window.innerHeight and window.innerWidth properties. Follow these steps to get the window dimension value in Blazor WebAssembly.
[Index.razor]
@page "/"
@inject IJSRuntime JsRuntime
<h1>Window Dimensions</h1>
<button class="btn btn-primary" @onclick="OnButtonClick">Get Dimensions</button><br /><br />
<p>Window Height: @Height</p>
<p>Window Width: @Width</p>
@code {
public int Height { get; set; }
public int Width { get; set; }
private async Task OnButtonClick()
{
var dimension = await JsRuntime.InvokeAsync<WindowDimension>("getWindowDimensions");
Height = dimension.Height;
Width = dimension.Width;
}
public class WindowDimension
{
public int Width { get; set; }
public int Height { get; set; }
}
}
@page "/"
@inject IJSRuntime JsRuntime;
<button class="btn btn-primary" @onclick="OnButtonClick">Call C# from JS</button><br /><br />
<p>@content</p>
@code {
private static string content { get; set; }
[JSInvokable] // Return call back from JavaScript with parameter to C#.
public static void JStoCSCall(string value)
{
content = value;
}
private async Task OnButtonClick() // Invoked by button clicking and calls JavaScript function.
{
await JsRuntime.InvokeAsync<object>("invokeJSfromCS");
}
}
[index.html]
<body>
. . .
. . .
<script>
Function invokeJSfromCS () {
var value = "C# Method called from JavaScript with parameter";
// Invoke to call C# function from JavaScript with parameter.
DotNet.invokeMethod('BlazorWasmApp', 'JStoCSCall', value);
}
</script>
</body >
In the following example, the cookie consent banner temple will display to notify you to accept cookies. Follow the below steps to create a consent cookie in Blazor.
1. Configure the HttpContextAccessor and CookiePolicyOptions to the startup file to create a consent cookie.
[Startup.cs]
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
public class Startup
{
. . .
. . .
public void ConfigureServices(IServiceCollection services)
{
. . .
. . .
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddHttpContextAccessor();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
. . .
. . .
app.UseCookiePolicy();
}
}
2. Now, add the Cookie consent banner template as a Razor component under the Shared folder.
Blazor doesn’t manipulate the DOM directly at C# side. You cancall the JavaScript method by using JavaScript Interop to get an element by ID or class.
The getElementsByClassName() method returns a collection of all elements in the document with the specified class names.
The getElementById() method returns a collection of all elements in the document with the specified ID names.
[Index.razor]
@page "/"
@inject IJSRuntime JsRuntime
<h1 id="headingElement">Hello, world!</h1>
<p class="para-element">Welcome to your new app.</p>
@code {
protected override async void OnAfterRender(bool firstRender)
{
await JsRuntime.InvokeVoidAsync("elementId");
}
}
[_Host.cshtml]
<body>
. . .
. . .
<script>
function elementId() {
// Get element with the specified ID name
var idValue = document.getElementById("headingElement");
console.log(idValue.innerHTML);
// Get element with the specified Class name
var classValue = document.getElementsByClassName("para-element");
console.log(classValue[0].innerHTML);
}
</script>
</body>
In Blazor, you can call a JavaScript method using JavaScript interop to scroll the page to the top position.
In the following code, the button event triggers when the button is clicked and scrolls to the page top.
[Index.razor]
@page "/"
@inject IJSRuntime JsRuntime
<div style="background-color:lightgrey;padding:60px 60px 1000px">
<h2>Blazor App</h2>
This example demonstrates how to scroll to the top based on the button click event.<br />
Scroll down and click the button; it scrolls to the top position.
</div>
<div><br />
<button @onclick="OnButtonClick" class="btn btn-primary">Click Button</button>
</div>
@code {
private async void OnButtonClick()
{
await JsRuntime.InvokeVoidAsync("OnScrollEvent");
}
}
[_Host.cshtml]
<body>
. . .
. . .
<script>
// When the user clicks the button, the page scrolls to the top
function OnScrollEvent() {
document.documentElement.scrollTop = 0;
}
</script>
</body>
<body>
. . .
. . .
<script>
function copyClipboard() {
/* Get the text field */
var copyText = document.getElementById("form-control");
/* Select the text field */
copyText.select();
/* Copy the text inside the text field */
document.execCommand("copy");
/* Alert the copied text */
alert("Copied the text: " + copyText.value);
}
</script>
</body>
To use jQuery UI components in a Blazor application, follow these steps:
Add jQuery reference to host the page
Add jQuery and its UI component script and style references in the ~/_Host.cshtml file.
Initialize the jQuery component
Initialize the jQuery components in the OnAfterRender lifecycle method in your Blazor application by using the JavaScript Interop’s InvokeVoidAsync method.
@page "/"
@inject IJSRuntime jsRuntime
<div id="top">
<a href="#section1">Go Section 1</a>
<a href="#section2">Go Section 2</a>
<a href="#section3">Go Section 3</a>
</div><br>
<div id="section1">
In the web project, pagination is a very important part where huge numbers of records are listed from the
database. In that case, Ajax pagination is a preferable way because it will help to improve the User
Interface
of your website. You'll easily be able to implement the Ajax pagination with our PHP Pagination class.
Pagination class helps to generate the pagination links and get the records from the database using Ajax.In
the
web project, pagination is a very important part where huge numbers of records are listed from the database.
In
that case, Ajax pagination is a preferable way because it will help to improve the User Interface of your
website. You'll easily be able to implement the Ajax pagination with our PHP Pagination class. Pagination
class
helps to generate the pagination links and get the records from the database using Ajax.
</div>
<br /><br />
<div id="section2">
<a href="#top">BackToTop</a><br />
In the web project, pagination is a very important part where huge numbers of records are listed from the
database. In that case, Ajax pagination is a preferable way because it will help to improve the User
Interface
of your website. You'll easily be able to implement the Ajax pagination with our PHP Pagination class.
Pagination class helps to generate the pagination links and get the records from the database using Ajax.In
the
web project, pagination is a very important part where huge numbers of records are listed from the database.
In
that case, Ajax pagination is a preferable way because it will help to improve the User Interface of your
website. You'll easily be able to implement the Ajax pagination with our PHP Pagination class. Pagination
class
helps to generate the pagination links and get the records from the database using Ajax.
</div>
<br /><br />
<div id="section3">
<a href="#top">BackToTop</a><br />
In the web project, pagination is a very important part where huge numbers of records are listed from the database. In that case, Ajax pagination is a preferable way because it will help to improve the User Interface of your website. You'll easily be able to implement the Ajax pagination with our PHP Pagination class.
Pagination class helps to generate the pagination links and get the records from the database using Ajax. In the
web project, pagination is a very important part where huge numbers of records are listed from the database.
In
that case, Ajax pagination is a preferable way because it will help to improve the User Interface of your website. You'll easily be able to implement the Ajax pagination with our PHP Pagination class. Pagination
class
helps to generate the pagination links and get the records from the database using Ajax.
</div>
@code {
protected override async void OnAfterRender(bool firstRender)
{
if (firstRender)
{
await jsRuntime.InvokeVoidAsync("renderjQuery");
}
base.OnAfterRender(firstRender);
}
}
[script.js]
function renderjQuery() {
$('a[href*=\\#]:not([href=\\#])').on('click', function () {
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.substr(1) + ']');
if (target) {
$('html,body').animate({
scrollTop: target.offset().top
}, 1000);
return false;
}
});
}
To avoid memory leaks, dispose the DotNetObjectReference instance created by a component properly and allow proper garbage collection. The DotNetObjectReference instance should be disposed either at component side or JavaScript side.
Use the following patterns to dispose DotNetObjectReference at the component level.
Implement IDisposable interface in the component.
Add Dispose method and dispose DotNetObjectReference object inside the
Dispose method.
To add Bing Maps to a Blazor application follow the steps.
Include the Bing Maps Web API scripts in the index.html/_Host.cshtml, This is used to retrieve the Bing Maps-related information by sending a request to the Bing Maps server and loading the same to the Blazor application.
Initialize maps in a Blazor application by using a JavaScript interop in the razor file [index.razor].
Please find the sample below.
[script.js]
function loadBingMap() {
var map = new Microsoft.Maps.Map(document.getElementById('map'), {});
var pushpin = new Microsoft.Maps.Pushpin(map.getCenter(), null);
map.entities.push(pushpin);
return "";
}
To
use jQuery UI components in a Blazor application follow the steps:
Reference the source scripts for jQuery and its UI components.
Create the elements required for rendering jQuery UI components in the razor page [index.razor].
Initialize the jQuery components in the OnAfterRender lifecycle method in your Blazor application by using the JavaScript Interop’s InvokeVoidAsync method.
@page "/"
@inject IJSRuntime jsRuntime
<h1>jQuery UI Components in Blazor</h1>
<br />
<h2>jQuery Accordion Component</h2>
<br />
<div id="accordion">
<h3>ASP.NET</h3>
<div>
<p>
Microsoft ASP.NET is a set of technologies in the Microsoft .NET Framework for building Web applications and XML Web services.
ASP.NET pages execute on the server and generate markup such as HTML, WML, or XML that is sent to a desktop or mobile browser.
ASP.NET pages use a compiled,event-driven programming model that improves performance and enables the separation of application logic and user interface.
</p>
</div>
<h3>ASP.NET MVC</h3>
<div>
<p>
The Model-View-Controller (MVC) architectural pattern separates an application into three main components: the model, the view, and the controller.
The ASP.NET MVC framework provides an alternative to the ASP.NET Web Forms pattern for creating Web applications.
The ASP.NET MVC framework is a lightweight, highly testable presentation framework that (as with Web Forms-based applications) is integrated with existing ASP.NET features, such as master pages and membership-based authentication.
</p>
</div>
<h3>JavaScript</h3>
<div>
<p>
JavaScript (JS) is an interpreted computer programming language.
It was originally implemented as part of web browsers so that client-side scripts could interact with the user, control the browser, communicate asynchronously, and alter the document content that was displayed.
More recently, however, it has become common in both game development and the creation of desktop applications.
</p>
</div>
</div>
<br />
<div class="jquery-btn">
<button>Click Me</button>
</div>
<br />
<p>Clicked: <span class="click-count">0</span></p>
<br />
@code {
protected override async void OnAfterRenderAsync(bool firstRender)
{
await jsRuntime.InvokeVoidAsync("renderjQueryComponents");
await base.OnAfterRenderAsync(firstRender);
}
}
[script.js]
var clickCount = 0;
function renderjQueryComponents() {
$("#accordion").accordion();
$(".jquery-btn button").button();
$(".jquery-btn button").click(function () {
console.log('Clicked');
$('.click-count')[0].innerText = ++clickCount;
});
}
[script.js]
function initialize() {
var latlng = new google.maps.LatLng(40.716948, -74.003563);
var options = {
zoom: 14, center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById ("map"), options);
}
In the above example, Google Maps is initialized in the OnAfterRenderAsync life cycle method. By invoking it using a JavaScript interop, this will initialize Google Map API when the page is rendered.
There is
no direct way to detect whether the page is loaded on mobile or desktop in
Blazor. We have to find out through the userAgent property from the JavaScript
side using a JSInterop call. In order to find out, add a “script.js” file in
the wwwroot folder and include the isDevice method call. You can then invoke
the isDevice method to identify the correct device.
Refer to
the following code for further details.
[wwwroot/script.js]
function isDevice() {
return /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini|mobile/i.test(navigator.userAgent);
}
If you want to show a message using a simple browser alert message box, it is easy to do in Blazor. In Blazor, you can call a JavaScript method using JavaScript interop.
In the following code snippets, the text entered in the text box will be displayed in the alert box. In order to call the JavaScript method in Blazor, you should register the method in the browser window class. You can pass the message you want to show by passing method parameters in the JSRuntime.InvokeAsync method.
You can use a third party API, such as Ipify, to get the IP address of the current request in Blazor. The script api.ipify will return the IP address in JSON format. But this is a workaround. As of now, there is no way to achieve this. In the following code snippet, the IP address will be retrieved from the Ipify API through a JS interop call to the Blazor server.
[_Host.cshtml/index.html]
<script>
function GetAddress() {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "https://api.ipify.org?format=jsonp&callback=DisplayIP";
document.getElementsByTagName("head")[0].appendChild(script);
};
function DisplayIP(response) {
document.getElementById("text").innerHTML = "Your IP Address is " + response.ip;
}
</script>
We can focus an InputText Blazor element not directly but by using JavaScript in Blazor. We can set an ID for the InputText and then pass it to JavaScript using interop by method InvokeVoidAsync. In the JavaScript function, use the focus DOM input method for focusing the input element with the received ID from Blazor.
Refer to the following code snippet.
[script.js]
function focusInput(id) {
document.getElementById(id).focus();
}
We can change a C# property’s value in Blazor from JavaScript by invoking the method DotNet.invokeMethodAsync in the script file (.js file). It takes the parameters Assembly name (Application name), the method name (public static method), and method parameter where we can change the C# static parameter.
Refer to
the following code snippet for more details.
[script.js]
function ChangeContentJS() {
DotNet.invokeMethodAsync('InvokeFromJsApp', "ChangeParaContentValue", "New Content");
}
[Index.razor]
@page "/"
@inject IJSRuntime JSRuntime
<h1>Change C# property value from JavaScript</h1>
<br />
<button @onclick='ButtonClickHandler'>Change Content - JS</button>
<br />
<p>@ParaContent</p>
@code {
public static string ParaContent = "Some Text Content";
public async Task ButtonClickHandler()
{
await JSRuntime.InvokeAsync<string>("ChangeContentJS");
}
[JSInvokable]
public static void ChangeParaContentValue(string value)
{
ParaContent = value;
}
}
In the previous
example, we have changed the ParaContent C# field value from the JavaScript by
calling the static method ChangeParaContentValue from JavaScript, along
with the new value as one of parameters in invokeMethodAsync.
The C# method should be defined as static and it should have a JSInvokable attribute.
The arguments in the JavaScript method Dotnet.invokeMethodAsync should be
To detect keypress event in a div tag, use the @onkeydown event on the current element. In the created example there is a div element with keydown event, and on rendering, the focus to the div element is set by using the JS Interop.
Error CS1061 ‘IJSRuntime’ does not
contain a definition for ‘Current’ and no accessible extension method ‘Current’
accepting a first argument of type ‘IJSRuntime’ could be found (are you missing
a using directive or an assembly reference?)
Solution
In ASP.NET Core 3.0.0-preview3, the Microsoft.Interop.JSRuntime.Current has been removed.
Add the .NET function invoke statement to a script in the head of Pages/_Host.cshtml file.
<script>
function CSMethod() {
DotNet.invokeMethodAsync('BlazorTestApp', 'CSCallBackMethod');
}
</script>
Here we are defining a JavaScript function “CSMethod”. This function will have a callback to our .NET function “CSCallBackMethod” which is defined in index.razor.
To invoke C# method from JavaScript,
The method must be decorated with “JSInvokable” attribute.
The method must be public.
The method may either be static or instance-level (this is only supported by Blazor 0.5.0 and above).
In Blazor, IJSRuntime interface is used to invoke a JavaScript
function from .NET.
Using the InvokeAsync<T> method of IJSRuntime abstraction, we can call the JavaScript function. This method takes the function name and function parameters as the argument.
The
method CallJSMethod will
call JS function JSMethod by using
the JSRuntime.InvokeAsync method.
Important notes
Do not write your JS code in the .cshtml file.
This is not allowed in Blazor and the compiler will throw an error. Always put
your JS code in the wwwroot/index.html file.
Always add your custom <script> tag after “<script
src=”_framework/blazor.webassembly.js”> </script>” in the
<body> section of the index.html file. This is to ensure that your
custom script will execute after loading the “blazor.webassembly.js” script.
Currently, Blazor doesn’t provide any direct way to access the browser’s DOM or APIs. But there is an option to invoke/call JavaScript functions via JS Interop, thereby letting Blazor access the DOM and its APIs. In the below example we have accessed the button’s DOM element in the script by using javascript interop.
[_Host.cshtml/index.html]
<script>
function accessDOMElement() {
var btn;
// access DOM here
btn = document.getElementById('btn');
btn.innerText = "Button Textchanged";
}
</script>
You have to refer to the JavaScript method
implemented JS (external-script.js) file in index.html properly and then call the function from .NET using IJSRuntime.
The InvokeAsync accepts only params object[] args, so the array of objects is parsed as a single, top-level entry in args. You have to pass the array of objects as a single object by casting. The following code only passes the single array object.
await JSRuntime.InvokeAsync<object>("debugOut", new Person[] {
new Person{FirstName=" Nancy",LastName=” Davolio”},
new Person{FirstName=" Andrew", LastName=” Fuller”}
});
By casting the array into an object, it retrieves all the values.
await JSRuntime.InvokeAsync< object >("debugOut", (object) new Person[] {
new Person{FirstName=" Nancy",LastName=” Davolio”},
new Person{FirstName=" Andrew", LastName=” Fuller”}
});