Live Chat Icon For mobile
Live Chat Icon

Blazor FAQ

Find answers for the most frequently asked questions
Expand All Collapse All

Blazor detects the UI changes in common scenarios like EventCallback (button click, dropdown select, etc.), and refreshes the component. However, there are some situations in an app where a UI refresh needs to be triggered manually to re-render the component. The StateHasChanged method is used to force re-render a component UI.

@using System.Threading;

<h1>@Count</h1>

<button @onclick=@StartCountdown>Start Timer</button>

@functions {
    private int Count { get; set; } = 10;

    void StartCountdown()
    {
        var timer = new Timer(new TimerCallback(_ =>
        {
            if (Count > 0)
            {
                Count--;

                // Note that the following line is necessary because otherwise
                // Blazor would not recognize the state change and not refresh the UI
                InvokeAsync(() =>
                {

                    StateHasChanged();
                });
            }
        }), null, 1000, 1000);
    }
}
Permalink

Blazor application renders UI as a HTML content in client-side (browser). So, based on the width of the viewport in a device you can determine if it is a Desktop or a Mobile device and thus design responsive web pages accordingly.

The meta tag named “viewport” is used to design the webpage responsiveness and this is included in all Blazor applications, _Host.cshtml file in Blazor server-side application and index.html file in Blazor Web Assembly application. CSS styling makes designs responsive in Blazor apps.

For more details, refer to this link.

Permalink

String comparison with case insensitivity can be carried out using the String.Compare method, where the first and second parameters are the strings to be compared and the third parameter is for ignoring case sensitivity (case insensitive comparison).

Refer to the following code.

@page "/"

<h1>Case in-sensitive string comparision</h1>

<br />

<EditForm Model="@_stringCompare">
    String 1:
    <InputText id="string1" @bind-Value="_stringCompare.String1" />
    <br />
    String 2:
    <InputText id="string2" @bind-Value="_stringCompare.String2" />
    <br />
</EditForm>

<br />

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

<br />
<br />

<p>@Output</p>

<br />

@code {

    private StringCompare _stringCompare = new StringCompare();
    public string Output = "";

    public class StringCompare
    {
        public string String1 { get; set; }
        public string String2 { get; set; }
    }

    public async void Compare()
    {
        int CheckValue = String.Compare(_stringCompare.String1, _stringCompare.String2, true);
        Output = "Entered Strings are " + (CheckValue == 0 ? "" : "not ") + "Similar";
        await Task.Run(() => TimeOutMethod());
        Output = "";
        await Task.CompletedTask; 
    }

    void TimeOutMethod() => Task.Delay(3000).Wait();
}

You can download the reference sample here.

Permalink

To retrieve a selected value from the select control, you can use either the @bind or @onchange event.

//using @bind

@page "/dropdown"
<select class="form-control" @bind="@selectedString" style="width:150px">
         @foreach (var template in templates)
         {
                 <option value=@template>@template</option>
         }
</select>

<h5>Selected Country is: @selectedString</h5>

@code {
List<string> templates = new List<string>() { "America", "China", "India", "Russia", "England" };
string selectedString = "America";
    }
//using @onchange event

@page "/dropdown"

<select class="form-control"  @onchange="@OnSelect" style="width:150px">
         @foreach (var template in templates)
         {
                 <option value=@template>@template</option>
         }
</select>

<h5>Selected Country is: @selectedString</h5>

@code {
List<string> templates = new List<string>() { "America", "China", "India", "Russia", "England" };
string selectedString = "America";

void OnSelect (ChangeEventArgs e)
{
        selectedString = e.Value.ToString();
        Console.WriteLine("The selected country is : " + selectedString);
}
    }

Permalink

To access browser localStorage in Blazor apps, write a custom code or use a third party package. The difference between localStorage and sessionStorage  is: The localStorage is scoped to the user’s browser. If the user reloads the page or closes and reopens the browser, the state persists. Session storage is similar to local storage but the data in the session storage will be cleared after the session.

The Blazored.LocalStorage package can be used to access the browser’s local storage in Blazor. For this you need to install the package and add the service to the application.

[startup.cs]

public void ConfigureServices(IServiceCollection services)
{
         services.AddBlazoredLocalStorage();
}
[index.razor]
@page "/"
@inject Blazored.LocalStorage.ILocalStorageService localStorage

<h2>@Name</h2>
<button @onclick="Clear">Clear LocalStorage</button>
@code {
    public string Name;
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await localStorage.SetItemAsync("ID", "20019");
        await localStorage.SetItemAsync("Name", "John Smith");
        Name = "ID: " + await localStorage.GetItemAsync<string>("ID") + "Name : " + await localStorage.GetItemAsync<string>("Name");
    }
    public async void Clear()
   {
    //this will clear the local storage 
     await localStorage.ClearAsync();
    }

}

To access the local storage using the OnInitialized method, disable the ServerPrerender in _Host.cshtml.

Reference link: https://chrissainty.com/blazored-local-storage-v0-3-0-released/

Permalink

In Blazor, there are three ways to use different CSS files in different pages .

1. Use inline <style></style> tag to define the custom styling for the page.

2. Include a new CSS file in the page by using a JavaScript interop in the OnInitialized method.

[script.js]

function includeCss() {
     var element = document.createElement("link");
     element.setAttribute("rel", "stylesheet");
     element.setAttribute("type", "text/css");
     element.setAttribute("href", "css/external.css");//location of the css that we want     include for the page
     document.getElementsByTagName("head")[0].appendChild(element);
}
[index.razor]

@page “/”

<h1>Blazor Application</h1>

@code{
    protected override async void OnInitialized()
    {
        await JSRuntime.InvokeAsync<object>("includeCss");
     }
    }

3. Usedirect links of the CSS file via the <link> HTML element with its local or online reference in the href attribute.

<link href="StyleSheet.css" rel="stylesheet" />
Permalink

You can get the current page title in Blazor by using the “title” property of the document object in JavaScript and by using a .JavaScript interop since there is no DOM accessibility in Blazor. The following example shows how to get the page name.

[script.js]

window.getTitle = () => { 
       return document.title; 
};
@page "/"

@inject IJSRuntime jsRuntime

<h2>Page Title: @Title</h2>

<button class="btn btn-primary" @onclick="@GetTitle">Get Title</button>


@code {

    public string Title = "";
    
    public async void GetTitle()
    {
            Title = await jsRuntime.InvokeAsync<string>("getTitle");
     }
}
Permalink

A query string stores values in the URL that are visible to users. It is mostly used to pass the data from one page to another. In Blazor, the query string can be added using the NavigationManager. You can pass multiple parameters through the URL and access it via queryhelpers,

1. Install the package Microsoft.AspNetCore.WebUtilities from NuGet.

2. Use the QueryHelpers.ParseQuery.TryGetValue method

@page "/queryparam"
@inject NavigationManager navManager

<h3>Query Paramter Demo</h3>
<div>Id = @Id</div>
<div>Name = @Name</div>
@code{
 string Id { get; set; }
 string Name { get; set; }
 protected override void OnInitialized()
  {
            GetId();
            GetName();
   }
                public void GetId()
 {
        var uri = new Uri(navManager.Uri);
        Id =       Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(uri.Query).TryGetValue("id", out var type) ? type.First() : "";
        }
        public void GetName()
        {
            var uri = new Uri(navManager.Uri);
            Name = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(uri.Query).TryGetValue("name", out var type) ? type.First() : "";
        }
    }
Permalink

To perform the wait operation in Blazor, we need to use Task.Delay(Time in milliseconds) which will wait for the specified time before execution.

In the sample, we have delayed the count increment by a second by using the Task.Delay() method.

[counter.razor]
@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="@(async () => await Increment())">Click me</button>

@code {
private int currentCount = 0;

async Task Increment()
 {
        await Task.Delay(1000);
        currentCount++;
  }
}
Permalink

As of now, hot reload is not supported in Blazor, but it has been scheduled for the .NET 5 release. Please refer here for more information.

However, you can use the following command in the command prompt.

dotnet watch run debug 

Also, you must include the following file types in the .csproj file for which files you want to watch.

<DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="2.0.0" />
<ItemGroup>
    <Watch Include="..\**\*.razor" />
    <Watch Include="..\**\*.scss" />
    <Watch Include="..\**\*.cs" />
</ItemGroup>

Reference Link: https://stackoverflow.com/questions/58172922/is-there-any-hot-reload-for-blazor-server-side

Permalink

We can define specific instances for custom components by using @ref while defining the component in a Razor file.

In this sample, we have created the component reference for the card components with specific names. Using this reference, we can access the card component properties and modify them. Here we have changed the display property using the component reference.

[Card.razor]
<div class="card mb-3 @display" style="width: 18rem;">
 <div class="card-body">
      @ChildContent
 </div>
</div>

@code {
    string display = "";

    [Parameter]
    public RenderFragment ChildContent { get; set; }

    public void setVisible(bool visible)
    {
        if (visible)
        {
            display = "";
        }
        else
        {
            display = "d-none";
        }
    }
}
[index.razor]

@page "/"

<Card @ref="MyCardControl1">First Card</Card>

<Card @ref="MyCardControl2">Second Card</Card>

<button class="btn btn-primary" @onclick="Hide">Hide card</button>
<button class="btn btn-primary" @onclick="Show">Show card</button>

<button class="btn btn-primary" @onclick="Hide2">Hide card2</button>
<button class="btn btn-primary" @onclick="Show2">Show card2</button>
@code {

    Card MyCardControl1;
    Card MyCardControl2;

    private void Hide()
    {
        MyCardControl1.setVisible(false);
    }
    private void Show()
    {
        MyCardControl1.setVisible(true);
    }

    private void Hide2()
    {
        MyCardControl2.setVisible(false);
    }
    private void Show2()
    {
        MyCardControl2.setVisible(true);
    }
}
Permalink

To get current user details in a Blazor page, we need to inject the dependency IHttpContextAccessor. We need to configure the IHttpContextAccessor service in the startup.cs as follows.

[startup.cs]

public void ConfigureServices(IServiceCollection services)
{
            services.AddHttpContextAccessor();
}
[index.razor]

@page "/"
@using Microsoft.AspNetCore.Http
@inject IHttpContextAccessor httpContextAccessor

<h1>@UserName</h1>

@code {
 public string UserName;

 protected override async Task OnInitializedAsync()
 {
        UserName = httpContextAccessor.HttpContext.User.Identity.Name
 }
}
Permalink

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);
}

Refer the script file in the HTML page

[index.html/_Host.cshtml]

<head>
 .....
 <script src="~/script.js"></script>
 ....
</head>
[index.razor]

@page "/"
@inject IJSRuntime jsRuntime

<h1>Responsive</h1>

<button @onclick="FindResponsiveness">Find Device</button>
<h2>@isDevice</h2>
@code {
    private string isDevice { get; set; }
    private bool mobile { get; set; }
    public async Task FindResponsiveness()
    {
        mobile = await jsRuntime.InvokeAsync<bool>("isDevice");
        isDevice = mobile ? "Mobile" : "Desktop";

    }
}

For more details about mobile browser detection, refer to this link.

Permalink

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.

[script.js]
window. Alert = function(message) {
           alert(message);
}

Refer the script file in the HTML page

[index.html/_Host.cshtml]
<head>
 .....
 <script src="~/script.js"></script>
 ....
</head>
[index.razor]

@page "/"

<input type="text" @bind="message" />
<button class="btn btn-primary" @onclick="Alert"> Alert Me!</button>

@code {

string message = "";

    private async Task Alert()
    {
        await JSRuntime.InvokeAsync<object>("Alert", message);
    }
}
Permalink

You can redirect to a page in Blazor using the Navigation Manager’s NavigateTo method. In the following code snippet, it will redirect to the home page when this page gets loaded. Similarly, you can call NavigateTo() method from NavigationManager class anywhere to redirect to another page.

Refer to the following code snippet.

@page "/redirect"
@inject NavigationManager NavManager

<h1>Redirect Page</h1>

<p>Redirecting to Default Page</p>

@code {
    protected override void OnInitialized()
    {
        NavManager.NavigateTo("/");
    }
}
Permalink

A URL can be opened in a new tab either by using the NavLink component or by using JavaScript. In the NavLink component, we can specify the URL to be opened in a new tab in the href parameter. In interop’s IJSRuntime instances, the method InvokeAsyncwith parameters open, URL, and _blank are used. Here, the third parameter, _blank, is used to notify that the URL needs to be opened in the new tab.

@inject IJSRuntime jsRuntime

<NavLink href="/counter">Open</NavLink> 
<button @onclick="NavigateToNewTab">New Tab Navigation</button>

@code {

    public async Task NavigateToNewTab()
    {
        string url = "/counter";
        await jsRuntime.InvokeAsync<object>("open", url, "_blank");
    }
}
Permalink

You can change the default icon provider for Blazor by importing the required icons in the site.css (\wwwroot\css\site.css). The imported icons can be used throughout the application. In the sample, I’ve imported the Material theme icons and used them.

[site.css]

@import url('https://fonts.googleapis.com/icon?family=Material+Icons');
[~/Shared/NavMenu.razor]

<li class="nav-item px-3">
     <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
          <i class="material-icons"> accessibility </i>Home
     </NavLink>
</li>
<li class="nav-item px-3">
      <NavLink class="nav-link" href="counter">
           <i class="material-icons">autorenew</i> Counter
      </NavLink>
 </li>
<li class="nav-item px-3">
      <NavLink class="nav-link" href="fetchdata">Fetch data
      </NavLink>
</li>

In the sample, we have changed the default icons to the Material icons for the home page and counter.

Permalink

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>
[index.razor]

@page "/"
@inject IJSRuntime jsRuntime

<button @onclick="GetIp">Get IP!!!</button>
<textarea id="text" style="width:50%;height:40px;" />

@code{
          public async Task GetIp()
          {
                 await jsRuntime.InvokeAsync<object>("GetAddress");
          } 
}
Permalink

To load a dialog on demand in Blazor, we can create a modal dialog with a conditional attribute (@if). We can load the dialog in the HTML page by using the conditional attribute, which will render based on the Boolean property.
In the following code, we render the dialog on a button-click event in which the ShowPopup property will be set as true and the dialog will be shown on the page. We can remove the dialog by setting the ShowPopup property as false.

[index.razor]

@page "/"

@using BlazorApp.Data
@inject WeatherForecastService ForecastService

<h3>Dialog</h3>
<button class="btn btn-primary"
        @onclick="OpenDialog">
    Open Dialog
</button>
@if (ShowPopup)
{
    <!-- This is the popup to create or edit a forecast -->
    <div class="modal" tabindex="-1" style="display:block" role="dialog">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h3 class="modal-title">Modal Dialog</h3>
                    <!-- Button to close the popup -->
                    <button type="button" class="close"
                            @onclick="ClosePopup">
                        <span aria-hidden="true">X</span>
                    </button>
                </div>
                <!-- Edit form for the current forecast -->
                <div class="modal-body">
                    <input class="form-control" type="text"
                           placeholder="Celsius forecast"
                           @bind="forecasts[0].TemperatureC" />
                    <input class="form-control" type="text"
                           placeholder="Summary"
                           @bind="forecasts[0].Summary" />
                    <br />
                    <!-- Button to save the forecast -->
                    <button class="btn btn-primary"
                            @onclick="Save">
                        Save
                    </button>
                </div>
            </div>
        </div>
    </div>
}
@code {

    private WeatherForecast[] forecasts;

    protected override async Task OnInitializedAsync()
    {

        forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
    }
    bool ShowPopup = false;
    void OpenDialog()
    {
        // Open the Popup
        ShowPopup = true;
    }
    void ClosePopup()
    {
        // closes the Popup
        ShowPopup = false;
    }
    void Save()
    {
        //closes dialog after the save execution
        ShowPopup = false;
    }
}
Permalink

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();
}

Refer the script file in the HTML page

[index.html/_Host.cshtml]
<head>
 .....
 <script src="~/script.js"></script>
 ....
</head>
[Index.razor]

@page "/"

@inject IJSRuntime jsRuntime

<EditForm Model="@inputText">
    <InputText id="@InputID" @bind-Value="inputText.TextValue">You can enter some text...</InputText>
</EditForm>

<br />
<br />

<button @onclick="Focus">FOCUS!!!</button>

@code {

    public string InputID = "input-id";
    public string Output = "";

    public class InputTextClass
    {
        public string TextValue = "Some Random Text";
    }

    public InputTextClass inputText = new InputTextClass();

    public async Task Focus()
    {
        await jsRuntime.InvokeVoidAsync("focusInput", InputID);
    }
}
Permalink

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");
}

Refer the script file in the HTML page

[index.html/_Host.cshtml]
<head>
 .....
 <script src="~/script.js"></script>
 ....
</head>
[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
    • InvokeFromJsApp—AssemblyName.
    • ChangeParaContentValue—C# JSInvokable static method name.
    • “New Content”—method arguments.

You can download the reference sample here.

Permalink

Blazor does not have support to manipulate DOM elements directly, but we can still achieve it by using JavaScript interop. By creating a reference to an element, we can send it as a parameter to the JavaScript method via interop. In that JavaScript method, we can manipulate the DOM elements.

[script.js]
window.setElementText = (element, text) => {
    console.log(element);
    element.innerText = text;
}

Refer the script file in HTML page

[index.html/_Host.cshtml]
<head>
 .....
 <script src="~/script.js"></script>
 ....
</head>
[Counter.razor]

@page "/counter"

@using Microsoft.JSInterop
@inject IJSRuntime JSRuntime

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<p>Last button clicked: @lastButtonClicked</p>

<button @ref=button1 class="btn btn-primary" @onclick="@(()=>IncrementCount(@button1))">Click me</button>
<button @ref=button2 class="btn btn-primary" @onclick="@(()=>IncrementCount1(@button2))">Click me</button>


@code {

    private ElementReference button1;
    private ElementReference button2;

    private int currentCount = 0;
    private string lastButtonClicked = "None";

    private async void IncrementCount(ElementReference element)
    {
        currentCount++;
        lastButtonClicked = "Button 1";
        await JSRuntime.InvokeVoidAsync("setElementText", element, "Button 1 was clicked");

    }
    private async void IncrementCount1(ElementReference element)
    {
        currentCount++;

            lastButtonClicked = "Button 2";
            await JSRuntime.InvokeVoidAsync("setElementText", element, "Button 2 was clicked");
    }
}
Permalink

You can perform routing without changing the URL with the help of NavigationManager. You need to inject NavigationManager to use this service. You can use this service to perform routing programmatically.

Service Injection

@inject NavigationManager Navigate

<button @onclick="NavigateTo">Navigate</button>

@code {

      private void NavigateTo(){
             Navigate.NavigateTo("url");//specify required url here
      }
}
Permalink

We can handle the 404 error for query string parameters by checking whether the query is available in the parameter. If the parameter is not found, we can handle the error. We can also log an exception in Visual Studio by using the service ILogger in the application.

[Product.razor]
@page "/product-details/{ProductId:int}"
@using Microsoft.Extensions.Logging
@inject ILogger<ProductDetails> Logger

@if (details != null)
{
<h1>@details.ProductId</h1>
 <p>@details.Products</p>
}
else if (loadFailed)
{
    <h1>Product ID:@ProductId not found. Sorry, we could not load this product due to an error. Click <a href="/product-details/1001">here</a> to go back to first product page</h1>
    
}
else
{
  <h1>Loading...</h1>
}

@code {
    [Parameter] public int ProductId { get; set; }

    ProductDetails details;
    bool loadFailed;

    public List<ProductDetails> Data { get; set; }
    static ProductDetails Product_Details = new ProductDetails();

    protected override async Task OnParametersSetAsync()
    {
        try
        {
            loadFailed = false;
            details = await Product_Details.GetProductId(ProductId);
        }
        catch (Exception ex)
        {
            loadFailed = true;
            Logger.LogWarning(ex, "Failed to load product {ProductId}", ProductId);
        }
    }
    public class ProductDetails
    {
        public int ProductId { get; set; }
        public int In_Stock { get; set; }
        public int Sold { get; set; }
        public double Amount { get; set; }
        public string Country { get; set; }
        public string Product_Categories { get; set; }
        public string Products { get; set; }
        public string Order_Source { get; set; }
        public string Year { get; set; }
        public string Quarter { get; set; }

        public async Task<ProductDetails> GetProductId(int id)
        {
            List<ProductDetails> Product_Data = new List<ProductDetails>();
            Product_Data.Add(new ProductDetails { ProductId = 1001, In_Stock = 34, Sold = 51, Amount = 383, Country = "France", Product_Categories = "Accessories", Products = "Bottles and Cages", Order_Source = "Retail Outlets", Year = "FY 2015", Quarter = "Q1" });
            Product_Data.Add(new ProductDetails { ProductId = 1002, In_Stock = 4, Sold = 423, Amount = 3595.5, Country = "France", Product_Categories = "Accessories", Products = "Bottles and Cages", Order_Source = "Sales Person", Year = "FY 2015", Quarter = "Q1" });
            Product_Data.Add(new ProductDetails { ProductId = 1004, In_Stock = 38, Sold = 234, Amount = 1813.5, Country = "France", Product_Categories = "Accessories", Products = "Bottles and Cages", Order_Source = "Teleshopping", Year = "FY 2015", Quarter = "Q1" });
            Product_Data.Add(new ProductDetails { ProductId = 1005, In_Stock = 42, Sold = 127, Amount = 952.5, Country = "France", Product_Categories = "Accessories", Products = "Bottles and Cages", Order_Source = "App Store", Year = "FY 2015", Quarter = "Q1" });
            Product_Data.Add(new ProductDetails { ProductId = 1005, In_Stock = 36, Sold = 89, Amount = 668, Country = "France", Product_Categories = "Accessories", Products = "Bottles and Cages", Order_Source = "Retail Outlets", Year = "FY 2015", Quarter = "Q2" });
            if (id == Product_Data[0].ProductId)
            {

                return Product_Data[0];
            }
            else if (id == Product_Data[1].ProductId)
            {

                return Product_Data[1];
            }
            else if (id == Product_Data[2].ProductId)
            {

                return Product_Data[2];
            }
            else if (id == Product_Data[3].ProductId)
            {

                return Product_Data[3];
            }
            else if (id == Product_Data[4].ProductId)
            {

                return Product_Data[4];
            }
            else if(id == Product_Data[5].ProductId)
            {
                return Product_Data[5];
            }

            return null;
        }
    }
}

You can download the reference sample here

Permalink

Blazor will check for an HTML ID on initializing the HTML element. If such an ID does not exist on the page, then it will use the default handler to display messages. To display custom messages  on connection loss, we can define a div element with the ID components-reconnect-modal in the body of _Host.cshtml to manipulate the overlay that shows up in the case of a connection loss. If this element exists, this element’s class will be :

components-reconnect-show: A lost connection. The client is attempting to reconnect. Show the modal. Then, you can apply your custom styling to the screen overlay with CSS. If you want to remove them all, you can just choose not to display them at all.

components-reconnect-hide: An active connection is re-established to the server. Hide the modal.

components-reconnect-failed: Reconnection failed, probably due to a network failure. To attempt reconnection, call window.Blazor.reconnect().

components-reconnect-rejected: Reconnection rejected. The server was reached but refused the connection, and the user’s state on the server is lost. To reload the app, call location.reload().

Refer to this link for more details: https://docs.microsoft.com/en-us/aspnet/core/blazor/hosting-model-configuration?view=aspnetcore-3.1#reflect-the-connection-state-in-the-ui

[_Host.cshmtl]

<body>
……

<div id="components-reconnect-modal" class="my-reconnect-modal components-reconnect-hide">
<div class="show">
    <p>
        // Message when attempting to connect to server
    </p>
</div>
<div class="failed">
    <p>
        // Message when failing to connect
    </p>
</div>
<div class="rejected">
    <p>
        // Message when refused
    </p>
</div>
</div>

……
<app>
    @(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))
</app>

</body>
[site.css]

    .my-reconnect-modal > div {
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        z-index: 1000;
        overflow: hidden;
        background-color: #fff;
        opacity: 0.8;
        text-align: center;
        font-weight: bold;
    }

    .components-reconnect-hide > div {
        display: none;
    }

    .components-reconnect-show > div {
        display: none;
    }

    .components-reconnect-show > .show {
        display: block;
    }

    .components-reconnect-failed > div {
        display: none;
    }

    .components-reconnect-failed > .failed {
        display: block;
    }

    .components-reconnect-refused > div {
        display: none;
    }

    .components-reconnect-refused > .refused {
        display: block;
    }

You can download the reference sample here

Permalink

You can capture input keyboard events by attaching the event handler to the keyboard events such as Keydown, Keypress, or Keyup with the input control. In the following example, the keyboard event handler is attached to all these three events. If you want to identify which keyboard event is captured, you can get the type using the KeyboardEventArg.Type property.

[index.razor]

@page "/"

<input type="text" @onkeydown="KeyboardEventHandler " @onkeypress=" KeyboardEventHandler " @onkeyup="KeyboardEventHandler "/>

<h4>@KeyPressed </h4>
<h4>@EventInfo</h4>

@code {
    string KeyPressed = "";
    string EventInfo = "";
    private void KeyboardEventHandler(KeyboardEventArgs args)
    {
        KeyPressed = "Key Pressed is " + args.Key;
        EventInfo = "Event Type " + args.Type;
    }
}
Permalink

The lifecycle methods OnAfterRenderAsync and OnAfterRender are called only when a component has finished rendering. The element and component references are populated at this point. By using these methods, the user can activate third-party JavaScript libraries that operate based on the DOM elements.

Permalink

You can delay a task in Blazor by using the Task.Delay() method where the time set for the task to be delayed before proceeding to the next.

<h3>Timer: @Timer</h3>

@code {
    [Parameter] 
    public int Timer { get; set; } = 5;

    public async void StartTimerAsync()
    {
        while (Timer > 0)
        {
            Timer--;
            StateHasChanged();
            await Task.Delay(1000);
        }
    }

    protected override void OnInitialized()
        => StartAsync();
}
Permalink

Blazor provides support for suppressing events of the HTML DOM element in two ways

  • Suppressing default event
  • Suppressing event propagation

Suppressing default event:                                                                                                                        

The default events of the HTML DOM element can be suppressed by using the @on{Event}:preventDefault directive attribute provided in Blazor. This is useful in scenarios like suppressing the on key press event of an input text box.

<input type="text" @onkeypress:preventDefault />

You can also add your own event listener as done for event handling.

<input type="text" @onkeypress="EventHandlerMethod" @onkeypress:preventDefault />

Supressing event propagation:

HTML DOM element’s events tend to propagate some events to their parent element and then its parent element, and so on. Blazor provides support to supress the event propagation using the @on{EVENT}:stopPropagation directive attribute. This takes a Boolean variable as the input. This is visualized as follows.

<button @onclick:stopPropagation="true">Click</button>

As the stopPropagation attribute which takes the value of a Boolean variable can be bound to a property, the propagation can be stopped based on the user requirement.

Permalink

You can call the preventDefault action in onclick event of an anchor tag. Refer to the following code sample to prevent opening a link when the link is clicked.

<a href="https://www.syncfusion.com/" target="_blank" @onclick:preventDefault>Syncfusion</a>

This feature was made available from .NET Core 3.1 Preview 2 for Blazor.

You can also perform custom action for onclick in the anchor tag by defining the same onclick event and mapping it to custom action.

<a href="https://www.syncfusion.com/" target="_blank" @onclick:preventDefault  @onclick="@OnClick">Syncfusion</a>
@code {
         public void OnClick(){
              //triggers on click
         }
}
Permalink

You can call JavaScript methods from the Blazor pages with the help of JavaScript Interop by injecting the dependency IJSRuntime into the razor page.

[script.js]
function buttonClick() {
    // this function triggers on button click
}

Then refer the script in the HTML page of the blazor application.

<script src="~/script.js"></script>
[index.razor]
@page "/"
@inject IJSRuntime jsRuntime

<button @onclick="onbuttonclick"> Button  </button>

@code {
    protected void onbuttonclick (MouseEventArgs args)
    {
        await jsRuntime.InvokeVoidAsync<object>("buttonClick ");
    }
}

Check this link for more information.

Permalink

To debug a client-side Blazor app in a browser:

  1. Close the all instances in Chrome.
  2. Run the Blazor app in Chrome (version 70 or later).
  3. Open Win + R and run following command.
"%programfiles(x86)%\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222 http://localhost:52902/
  • Now the Blazor app is running.
  • Then hit Shift+Alt+D on Windows or Linux and Shift+Cmd+D on macOS.

Reference link:

https://docs.microsoft.com/en-us/aspnet/core/blazor/debug?view=aspnetcore-3.1

https://www.hanselman.com/blog/CompilingCToWASMWithMonoAndBlazorThenDebuggingNETSourceWithRemoteDebuggingInChromeDevTools.aspx

Permalink

There are two methods to call a method from JavaScript:

  • DotNet.invokeMethod
  • DotNet.invokeMethodAsync

The syntax of calling a C# method from JavaScript is as follows.

DotNet.invokeMethodAsync('C# method assembly name', 'C# Method Name');

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).
  • The Identifier for the method must be unique.
  • The method must be nongeneric.
@page "/jsinterop"
@inject IJSRuntime JsRuntime;

<button @onclick="WriteToConsole">Call .NET Method</button>
<br />
<p>@message</p>


@code {
    protected static string message { get; set; }

    [JSInvokable]
    public static void CSCallBackMethod()
    {
        message = "C# Method invoked";
    }

    private async Task WriteToConsole()
    {
        await JsRuntime.InvokeAsync<object>("CSMethod");
    }
}

Reference LinkReference link

https://www.freecodecamp.org/news/how-to-implement-javascript-interop-in-blazor-9f91d263ec51/

Permalink

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>
[index.razor]

@page "/"
@inject IJSRuntime jsRuntime

<h1>@Title</h1>

<button id="btn" @onclick="UpdateTitle">Update Title</button>

@code {
    private string Title { get; set; } = "Hello, World!";

    private async void UpdateTitle()
    {
        await jsRuntime.InvokeAsync<object>("accessDOMElement");
        Title = "Hello, Blazor!";
    }
}
Permalink

Inject NavigationManager in razor.

@inject NavigationManager NavigationManager

Use Uri from NavigationManager to get the current URL.

string currentUrl = NavigationManager.Uri;

Sample code

@page "/sample"
@inject NavigationManager NavigationManager

<p>@currentUrl</p>

@code {
    private string currentUrl;

    protected override void OnInitialized()
    {
        currentUrl = NavigationManager.Uri;
    }
}
Permalink

You can use the following CSS classes to apply your own styles to validation messages.

CSS class name Added DOM element 
valid/invalid Added to the <input> element of DOM 
validation-errors  Added to the dynamically created <ul>
element while using the
<ValidationSummary> tag 
validation-message Added to the dynamically created <div> / <li>
element which holds to error message. 

<div> – created while using
<ValidationMessage> tag 
<li> – created while using
<ValidationSummary> tag 
modified Added to the <input> element after modifying the default value. 
Permalink

You have to use JS Interop to create a cookie in Blazor.

[Razor Page]

@page "/"
@inject IJSRuntime JSRuntime

@code {

    private async void CreateCookie(string name, string value, int days)
       {
            var test = await JSRuntime.InvokeAsync<string>("methods.CreateCookie", name, value, days);
       }
}

[Script file]

window.methods = {
    CreateCookie: function (name, value, days) {
     var expires;
     if (days) {
        var date = new Date();
         date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
          expires = "; expires=" + date.toGMTString();
     }
      else {
         expires = "";
     }
      document.cookie = name + "=" + value + expires + "; path=/";
   }    
}

Refer to to How do I create a cookie client-side using Blazor for more information.

Permalink

You have to define and bind the EditContext with EditForm and then call the method editContext.Validate() on button click to manually trigger the validation.

@using System.ComponentModel.DataAnnotations;

<EditForm EditContext="@EC">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <div class="form-group d-flex justify-content-between">
        <label class="col-form-label col-3" for="name">Time</label>
        <InputText bind-Value="@model.Name" id="name" Class="form-control" />
    </div>
    <button type="button" onclick="@SubmitHandler" class="btn btn-primary">Submit</button>
</EditForm>
@code {
    public class ModelClass
    {
        [Required]
        public string Name { get; set; }
    }
    private ModelClass model { get; set; } = new ModelClass { Name = "" };
    private EditContext EC { get; set; }
    protected override void OnInitialized()
    {
        EC = new EditContext(model);
        base.OnInitialized();
    }
    private void SubmitHandler()
    {        
        EC.Validate(); // manually trigger the validation here
    }
}
Permalink

DOM elements are hidden using the hidden attribute. You can conditionally use any .NET parameter to set this attribute to hide the DOM elements.

@page "/"
    
   <p hidden="@IsShow">I am Blazor</p>
    
   <button @onclick="@Show">Show/Hide</button>
  
 @code {
       private bool IsShow   {get;set;} = false;
       private void Show()
       {
           IsShow =   !IsShow;
       }      
 } 
Permalink

DOM attributes are rendered based on .NET parameters. If the parameter value is true, the attribute is rendered minimized, otherwise it’s not. Refer to the code example to render the checked attribute conditionally.

 <input type="checkbox" checked="@IsChecked">
  
 @code {
     [Parameter]
     public bool IsChecked { get; set; }
 } 
Permalink

You can check whether a type of WebAssembly is an object in global scope, but the global scope is not a feasible one across different JavaScript environments, such as a main browser thread, worker, Node.js.

The more feasible solution is as follows.

 const supported = (() => {
      try {
 if (typeof WebAssembly === "object"
             && typeof WebAssembly.instantiate === "function") {
             const module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00));
             if (module instanceof WebAssembly.Module)
                 return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
         }
     } catch (e) {
     }
     return false;
 })();
  
 console.log(supported ? "WebAssembly is supported" : "WebAssembly is not supported");   

Refer to this StackOverflow link for more information.

Permalink

Share with

Share on twitter
Share on facebook
Share on linkedin

Couldn't find the FAQs you're looking for?

Please submit your question and answer.