Tap the power of breath, mantra, mudra, and dhyana.
Online course in Advanced Ajapa Japa and Shambhavi Mudra Meditation by Bipin Joshi.


Display tabular data using QuickGrid for Blazor

Displaying tables or grids is one of the most common requirements in web applications. There are plenty of third-party grid components available for ASP.NET Core and Blazor. However, if you require basic tabular display with sorting, paging, and filtering abilities QuickGrid component developed by the Blazor team is all you need. In this article we will explore some of the features and abilities of QuickGrid.

The QuickGrid component for Blazor can be used to display data from any IQueryable or it can get the data from a GridItemsProvider callback. In the examples that follow we are primarily going to use Entity Framework Core's IQueryable as our data source. The QuickGrid component can be used with Blazor Server as well as WebAssembly but we are going to use Blazor Server for our examples.

Before we use the QuickGrid component, let's first add EF Core entity classes and a DbContext class. Begin by creating a new Blazor Web App with interactive render mode of Server.

and...

Once the project is created, add the following NuGet packages using the NuGet package manager dialog:

  • Microsoft.EntityFrameworkCore.SqlServer
  • Microsoft.AspNetCore.Components.QuickGrid
  • Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter

The first package is required for EF Core functionality. The second package provides the QuickGrid component for Blazor. And the third package is an adapter for EF Core as required by the QuickGrid component. If you aren't using EF Core (say, you are using some in-memory IQueryable) you don't need to add the first and the third package.

Now add a new folder named DataAccess and create a new entity class in it called Employees.

public class Employee
{
    public int EmployeeID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Title { get; set; }
    public DateTime BirthDate { get; set; }
}

Then create a custom DbContext class called AppDbContext as shown below:

public class AppDbContext:DbContext
{
    public DbSet<Employee>
        Employees { get; set; }

    public AppDbContext(DbContextOptions
    <AppDbContext> options):base(options)
    {

    }
}    

And add the database connection string in appsettings.json.

"ConnectionStrings": {
    "AppDb": "data source=.;initial catalog=Northwind;
    integrated security=true;Encrypt=False"
    }    

Next, add a new Razor Component named QuickGridSample.razor in the Pages folder.

Assign a page URL to the component and also inject the AppDbContext in it.

@page "/quickgridsample"
@using DataAccess
@inject AppDbContext db

Now it's time to put the QuickGrid component to use. Write the following markup in the QuickGridSample component.

<h3>Blazor QuickGrid Sample</h3>
<QuickGrid Items="@db.Employees">
    <PropertyColumn Property="@(e => e.EmployeeID)" 
    Sortable="true" IsDefaultSortColumn="true" />
    <PropertyColumn Property="@(e => e.FirstName)" 
    Sortable="true" />
    <PropertyColumn Property="@(e => e.LastName)" 
    Sortable="true" />
    <PropertyColumn Property="@(e => e.Title)" 
    Sortable="true" />
    <PropertyColumn Property="@(e => e.BirthDate)" 
    Format="yyyy-MM-dd" 
    Sortable="true" />
</QuickGrid>    

As you can see, Items parameter of QuickGrid points to the Employees DbSet. It contains five PropertyColumn elements. The QuickGrid columns can either be of type PropertyColumn or TemplateColumn. A PropertyColumn displays data from a property as indicated by the Property parameter. The Sortable indicates whether that column can be sorted by clicking on the column header. The IsDefaultSortColumn indicates whether that column should be sorted by default when the grid is rendered. The BirthDate column also uses Format to specify the date format.

Run the application and you should see QuickGrid as shown below:

Check how columns can be sorted by clicking on the column header.

Next, we will add a TemplateColumn for displaying Full Name. Add the following immediately after the BirthDate column.

<TemplateColumn Title="Full Name">
    <ChildContent>
        <span>@context.FirstName 
        @context.LastName</span>
    </ChildContent>
</TemplateColumn>

The Title specifies the column heading. By default, a PropertyColumn uses the property name as the column heading. You can use Title with a PropertyColumn and TemplateColumn to display a custom column heading. Inside, the ChildContent section displays FirstName and LastName properties using the @context. After adding the TemplateColumn the grid looks like this (some columns have been trimmed from the image for clarify):

Implementing sorting for a TemplateColumn requires a bit more work. Let's add that too.

Add @code block and OnInitialized() method as shown below:

@code 
{    
    GridSort<Employee> sortByFullName;    

    protected override void OnInitialized()
    {
        sortByFullName = GridSort<Employee>
            .ByAscending(e => e.FirstName)
            .ThenAscending(e => e.LastName);
    }    
}

We create a GridSort object that specifies the sorting details. In this case we want to sort by FirstName and LastName. The sortByFullName is then supplied to the TemplateColumn like this :

<TemplateColumn Title="Full Name" 
Sortable="true" 
SortBy="@sortByFullName">
    <ChildContent>
        <span>@context.FirstName 
        @context.LastName</span>
    </ChildContent>
</TemplateColumn>

As you can see, we set the Sortable to true and SortBy to @sortByFullName. Run the application and check the sorting for Full Name column also.

Next, we will add paging to our grid. To do so we use PaginationState object as shown below:

@code
{
    GridSort<Employee> sortByFullName;
    PaginationState pager;

    protected override void OnInitialized()
    {
        sortByFullName = GridSort<Employee>
            .ByAscending(e => e.FirstName)
            .ThenAscending(e => e.LastName);

        pager = new PaginationState 
        { ItemsPerPage = 3 };
    }
}    

We create a PaginationState object and set its ItemsPerPage property to 3. This PaginationState object is linked with the QuickGrid as follows:

<QuickGrid Items="@db.Employees" 
Pagination="@pager">
    ...
    ...
</QuickGrid>
<Paginator State="@pager" />

We set the Pagination parameter of QuickGrid to the pager object so that the grid is aware of the paging properties. We also add Paginator component that displays a page navigator UI. Note that the column definitions are omitted from the above markup for the sake of clarity.

The following figure shows a sample run of the application after implementing the paging.

As you can see now the grid displays only three rows at a time. And a pager is rendered at the bottom of the grid where we placed the Paginator component.

So far so good. Now we will add filtering ability to our grid. We would like to filter our grid on the basis of Full Name. Since our grid will now be showing filtered data, we can't set db.Employees to Items parameter. Instead, we will set Items to the filtered data. And the filtered data will come from a custom property named FilteredData.

Let's add FilteredData property to the @code block.

string fullnameFilter;    

IQueryable<Employee> FilteredData
{
    get
    {
        if (string.IsNullOrWhiteSpace
        (fullnameFilter))
        {
            return db.Employees;
        }
        else
        {
            return db.Employees.Where
            (e => e.FirstName.Contains(fullnameFilter) 
            || e.LastName.Contains(fullnameFilter));
        }
    }
}    

As you can see, FilteredData property returns IQueryable. Inside the getter, we filter Employees based on fullnameFilter. The fullnameFilter is a string value as specified by the end user and it is captured from a textbox.

To capture the fullnameFilter value from a textbox we will modify the Full Name TemplateColumn like this:

<TemplateColumn Title="Full Name" 
Sortable="true" SortBy="@sortByFullName">
    <ColumnOptions>
        <div>
            <input type="search" 
                @bind="fullnameFilter" 
                @bind:event="oninput" />
        </div>
    </ColumnOptions>
    <ChildContent>
        <span>@context.FirstName 
            @context.LastName</span>
    </ChildContent>
</TemplateColumn>    

Notice the code shown in bold letters. We use ColumnOptions to indicate that the column has some options or settings. Inside, the ColumnOptions houses a textbox for entering a filter or search criteria. The @bind and @bind:event binds the textbox to fullnameFilter variable declared in the @code block.

Finally, point QuickGrid's Items parameter to FilteredData property as shown below (inside markup is omitted for clarity):

<QuickGrid Items="@FilteredData" 
Pagination="@pager"></QuickGrid>
...
...
</QuickGrid>

If you run the application, the Full Name column will show a options indicator. Clicking on the options indicator will pop the filter textbox like this:

If you enter some filter criteria, the grid will reflect the filtered output.

I think you must have got some idea about Blazor's QuickGrid component. As you can see QuickGrid provides the basic feature set for displaying tabular data. You can read more about QuickGrid in the official documentation here.

That's it for now! Keep coding!!


Bipin Joshi is an independent software consultant and trainer by profession specializing in Microsoft web development technologies. Having embraced the Yoga way of life he is also a meditation teacher and spiritual guide to his students. He is a prolific author and writes regularly about software development and yoga on his websites. He is programming, meditating, writing, and teaching for over 27 years. To know more about his ASP.NET online courses go here. More details about his Ajapa Japa and Shambhavi Mudra online course are available here.

Posted On : 08 January 2024