- The 'Virtualize' pre-build Blazor component was shipped from .Net5 framework.
- The concept behind making a virtualization component is to render the HTML content within the are of the viewport(i.e, visible area on a page).
- The most useful case to use this 'Virtualize' component is to display huge table content of data, by using this component renders the huge data as parts of data based on visible area dynamically.
- This dynamic loading data rendering will happen on scroll-up and scroll-down event implicitly nothing to worry about by us.
- This makes our website UI more user-friendly to render huge data without any UI delay.
Create A Sample WebAssembly Application:
The virtualization component can be used either in Blazor Server or Blazor WebAssembly applications. Here we are going to create a sample application using the Blazor WebAssembly template. For developing our sample application we can use any IDE of your choice but the most recommended are Visual Studio 2019(Supported VS for .Net5) or Visual Studio Code.
Implementation Technique Of Virtualize Blazor Component:
The Virtualize Blazor Component can be implemented in two different ways:
Items (Property) - The Virtualize component has the property 'Items' which accepts the collection of our data to be displayed. On passing our data to the 'Items' property the 'Virtualize' component will take of everything to render the data as parts depend on the visible area. So in this technique, we have to fetch all our data in a single API call and assigned it to the 'Items' property.- Items (Property)
- ItemProvider(delegate)
ItemProvider(delegate)- The Virtualize component has a delegate or callback event called 'ItemProvider'. This technique involves multiple API calls, which loads data per API call almost similar to the pagination technique but here data loads on the scroll. (Note:- My recommendation is to avoid this technique for production code because there few drawbacks, so if you interested in multiple API calls it's good to use the pagination approach. Might be it will be ready to use for production in the next release of .Net, until then avoid it. ).
A Sample Virtualize Component With Items Property:
Let's create a Virtualize component with a sample of fake data as follow.
Pages/Example.razor:(Html Part)
@page "/example" <div> <table class="table table-striped"> <thead> <tr> <th scope="col">My Todos</th> </tr> </thead> <tbody> <Virtualize Context="todo" Items="todos"> <tr> <td> @todo </td> </tr> </Virtualize> </tbody> </table> </div>
- (Line: 10-16) The 'Virtualize' component rendered.
- (Line: 10) The 'Items' property caries our data collection that going to rendered parts by parts based on visible area and page scroll.
- (Line: 10) The 'Context' specifies the parameter name for all child content expression. Using the name of the 'Context' parameter is used to bind the content inside of the component, in our example context is named as 'todo', the 'todo' is used for the binding. If we don't specify the name for the 'context' parameter then we have to use it directly inside of HTML for binding like '@context'.
- (Line: 13) Binding my todos data, since it is a simple string we used '@todo', for example, if it is an object then we have to bind like '@todo.Item', etc.
@code { private List<string> todos = new List<string>(); protected override async Task OnInitializedAsync() { for (int i = 0; i < 200; i++) { todos.Add($"My Itesm {i}"); } await Task.FromResult(0); } }Here I'm creating some collection todos fake data.
Let's check the rendered output as follows
Here on the left screen on the initial load, we can observe top item rendered is "My Item 0", after scrolling the page right screen the top item rendered is "My Item 4" now if you carefully understand and observe there will be no "My Item 0", "My Item 1", etc in the rendered element. This proves that the 'Virtualize' component renders the in-memory collection of data parts by parts on basis of visible UI.Create .Net5 Web API Sample:
Now we will create an API application that will be used by our blazor application where we replace the fake todos data with API data.
Note:
IF you have an existing API or If you have idea how to create an API just skip this section.
My sample endpoint looks something like below.
[Route("get-all")] [HttpGet] public async Task<IActionResult> AllTodos() { using (IDbConnection conn = Connection) { string query = @" SELECT Id, ItemName as Title, IsCompleted as Completed FROM Todo Order by Id ASC"; var result = (await conn.QueryAsync<Todo>(sql: query)).ToList(); return Ok(result); } }Here I'm fetching all todos records from my database, in this sample I used Dapper ORM to communicate with the database. Click here for implementing API using Dapper ORM.
My endpoint looks something like below.
Virtualization Component Items Property With API Data:
Now let's change our sample by consuming real API endpoint data to display inside of the virtualization component.
Now let's create our Typed HttpClient class as below
using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Json; using System.Threading.Tasks; using Blazorwasm.VirtualComponent.Sample.Models; namespace Blazorwasm.VirtualComponent.Sample.Clients { public class TodoClient { private readonly HttpClient _httpClient; public TodoClient(HttpClient httpClient) { _httpClient = httpClient; } public async Task<List<Todos>> GetAll() { var todos = await _httpClient.GetFromJsonAsync<List<Todos>>("/todos/get-all"); return todos; } } }Here we created HttpClient using the Typed technique, here we implemented our logic to fetch 'Todos' API data. Click here to understand different techniques to consume the web APIs in the Blazor application.
Now install the below package to register our Typed HttpClient in the Program.cs file.
Package Manager:
Install-Package Microsoft.Extensions.Http
.Net CLI
dotnet add package Microsoft.Extensions.Http
Now register our Typed HttpClient in the Program.cs file as below.Program.cs:
builder.Services.AddHttpClient<TodoClient>(client => { client.BaseAddress = new Uri("https://localhost:6001"); });
- Along with our typed HttpClient 'TodoClient,' we registered our API base address.
Pages/Example.razor:(Html Part)
@page "/example" @inject TodoClient _todoClient <div> <table class="table table-striped"> <thead> <tr> <th scope="col">Id</th> <th scope="col">Title</th> <th scope="col">Completed</th> </tr> </thead> <tbody> <Virtualize Context="todo" Items="todos"> <tr> <td> @todo.Id </td> <td> @todo.Title </td> <td> @todo.Completed </td> </tr> </Virtualize> </tbody> </table> </div>
- (Line: 2) Our 'TodoClient' type HttpClient injected(make sure to import the 'TocoClient' namespace in _Import.razor file)
- (Line: 13-25) The 'Virtualize' component declared and assigned our 'todos' collection to the 'Items' property.
@code { private List<Todos> todos = new List<Todos>(); protected override async Task OnInitializedAsync() { todos = await _todoClient.GetAll(); } }
- Fetching API data and assigning to 'todos' property which will be consumed by 'Virtualize' components Item property.
That's all about the Virtualization Component in Blazor WebAssembly Application.
Support Me!
Buy Me A Coffee
PayPal Me
Wrapping Up:
Hopefully, I think this article delivered some useful information on Blazor WebAssembly Virtualization Component. I love to have your feedback, suggestions, and better techniques in the comment section below.
Can virtualization be used with cards for example? Or this works only with tables? I want to display a page of products, 3 cards in a row.
ReplyDeleteVirtualization works based on the Item heights, In row with single card it might work, but with multiple cards in single row might not works.
DeleteI have clicked inside virtualize data, but scroll again moved to top instead of pointing the particula content.
ReplyDelete