Skip to main content

Blazor Grid

Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side paging & sorting.

Blazor Bootstrap: Grid Component

Grid Parameters

NameTypeDefaultRequiredDescriptionAdded Version
AllowDetailViewboolfalseGets or sets a value indicating whether the grid detail view is enabled.3.0.0
AllowFilteringboolfalseGets or sets the grid filtering.1.0.0
AllowPagingboolfalseGets or sets the grid paging.1.0.0
AllowRowClickboolfalseGets or sets the allow row click.1.9.5
AllowSelectionboolfalseGets or sets the grid selection.1.8.0
AllowSortingboolfalseGets or sets the grid sorting.1.0.0
AutoHidePagingboolfalseAutomatically hides the paging controls when the grid item count is less than or equal to the PageSize and this property is set to true.1.10.5
ChildContentRenderFragmentnull✔️Gets or sets the content to be rendered within the component.1.0.0
DataIEnumerable<TItem>nullGets or sets the grid data.1.4.3
DataProviderGridDataProviderDelegate<TItem>nullDataProvider is for items to render. The provider should always return an instance of GridDataProviderResult, and null is not allowed.1.0.0
DisableAllRowsSelectionFunc<IEnumerable<TItem>, bool>?Enable or disable the header checkbox selection.1.8.0
DisableRowSelectionFunc<TItem, bool>?Enable or disable the row level checkbox selection.1.8.0
EmptyDataTemplateRenderFragmentnull✔️Template to render when there are no rows to display.1.0.0
EmptyTextstringNo records to displayShows text on no records.1.0.0
EnumFilterSelectTextstringSelectGets or sets the enum filter select text.3.1.0
FiltersRowCssClassstringnullGets or sets the filters row css class.1.9.2
FiltersTranslationProviderGridFiltersTranslationDelegatenullFilters transalation is for grid filters to render. The provider should always return a 'FilterOperatorInfo' collection, and 'null' is not allowed.1.10.0
FixedHeaderboolfalseGets or sets the grid fixed header.1.10.3
GridContainerClassstringnullGets or sets the grid container css class.3.0.0
GridContainerStylestringnullGets or sets the grid container css style.3.0.0
HeaderRowCssClassstringnullGets or sets the header row css class but not the thead tag class.1.9.2
Heightfloat320 pixelsGets or sets the grid height.1.10.3
ItemsPerPageTextstringItems per page✔️Gets or sets the items per page text.1.9.5
PageSizeint10Gets or sets the page size.1.0.0
PageSizeSelectorItemsint[]new int[] { 10, 20, 50 }✔️Gets or sets the page size selector items.1.8.0
PageSizeSelectorVisibleboolfalseGets or sets the page size selector visible.1.8.0
PaginationItemsTextFormatstring{0} - {1} of {2} items✔️Gets or sets the pagination items text format.1.8.0
ResponsiveboolfalseGets or sets a value indicating whether Grid is responsive.1.0.0
RowClassFunc<TItem, string>?Gets or sets the row class.1.6.0
SelectionModeGridSelectionModeGridSelectionMode.SingleGets or sets the grid selection mode.1.8.0
SettingsProviderGridSettingsProviderDelegatenullSettings are for the grid to render. The provider should always return an instance of 'GridSettings', and 'null' is not allowed.1.0.0
THeadCssClassstring?nullGets or sets the thead css class.1.10.3
UnitUnitUnit.pxGets or sets the units.1.10.3
IMPORTANT

Grid requires either Data or DataProvider parameter, but not both.

Grid Callback Events

NameTypeDescriptionAdded Version
GridSettingsChangedEventCallback<GridSettings>This event is fired when the grid state is changed.1.0.0
OnRowClickEventCallback<GridRowEventArgs<TItem>>This event is triggered when the user clicks on the row. Set AllowRowClick to true to enable row clicking.1.9.5
OnRowDoubleClickEventCallback<GridRowEventArgs<TItem>>This event is triggered when the user double clicks on the row. Set AllowRowClick to true to enable row double clicking.1.9.5
SelectedItemsChangedEventCallback<HashSet<TItem>>This event is fired when the items selection changed.1.8.0

Grid Methods

NameReturn TypeDescriptionAdded Version
GetFilters()IEnumerable<FilterItem>Get filters.1.0.0
RefreshDataAsync(CancellationToken cancellationToken = default)TaskRefresh the grid data.1.0.0
ResetPageNumber()ValueTaskReset the page number to 1 and refresh the grid.1.4.3

GridColumn Parameters

NameTypeDefaultRequiredDescriptionAdded Version
ChildContentRenderFragmentnull✔️Gets or sets the content to be rendered within the component.1.0.0
ColumnClassFunc<TItem, string>?Gets or sets the column class.1.6.0
FilterablebooltrueIf true, filter is enabled. The filter is enabled or disabled based on the grid AllowFiltering parameter.1.0.0
FilterButtonColorButtonColorButtonColor.LightGets or sets the filter button color.3.0.0
FilterButtonCSSClassstring?nullGets or sets the filter button CSS class.3.0.0
FilterOperatorFilterOperatorFilterOperator.NoneGets or sets the filter operator.1.0.0
FilterTextboxWidthint0Gets or sets the filter textbox width in pixels.1.0.0
FilterValuestringnullGets or sets the filter value.1.0.0
FreezeboolfalseIndicates whether the column is frozen.1.10.4
FreezeDirectionFreezeDirectionFreezeDirection.LeftGets or sets the freeze direction of the column.1.10.4
FreezeLeftPositiondouble0Gets or sets the horizontal position of the column from left. It has no effect on non-positioned columns.1.10.4
FreezeRightPositiondouble0Gets or sets the horizontal position of the column from right. It has no effect on non-positioned columns.1.10.4
HeaderContentRenderFragmentnullGets or sets the header content.1.7.3
HeaderTextstringnullGets or sets the table column header text.1.0.0
HeaderTextAlignmentenumAlignment.StartGets or sets the header text alignment. Use Alignment.Start or Alignment.Center or Alignment.End.1.0.0
IsDefaultSortColumnboolfalseGets or sets the default sort column.1.0.0
PropertyNamestringnullGets or sets the property name. This is required when AllowFiltering is true.1.0.0
SortablebooltrueEnable or disable the sorting on a specific column. The sorting is enabled or disabled based on the grid AllowSorting parameter.1.0.0
SortDirectionSortDirectionSortDirection.NoneGets or sets the default sort direction of a column. Use SortDirection.Ascending or SortDirection.Descending1.0.0
SortKeySelectorExpression<Func<TItem, IComparable>>Expression used for sorting.1.0.0
SortStringstringnullGets or sets the column sort string. This string is passed to the backend/API for sorting. And it is ignored for client-side sorting.1.0.0
StringComparisonStringComparisonStringComparison.OrdinalIgnoreCaseGets or sets the StringComparison. Use StringComparison.CurrentCulture or StringComparison.CurrentCultureIgnoreCase or StringComparison.InvariantCulture or StringComparison.InvariantCultureIgnoreCase or StringComparison.Ordinal or StringComparison.OrdinalIgnoreCase.1.0.0
TextAlignmentAlignmentAlignment.StartGets or sets the text alignment. Use Alignment.Start or Alignment.Center or Alignment.End.1.0.0
TextNoWrapboolfalseGets or sets text nowrap.1.0.0

GridSettings Properties

NameTypeDefaultRequiredDescriptionAdded Version
PageNumberintPage number.1.0.0
PageSizeintSize of the page.1.0.0
FiltersIEnumerable<FilterItem>Current filters.1.0.0

Examples

Client side filtering

For filtering, AllowFiltering and PropertyName parameters are required. Add AllowFiltering="true" parameter to Grid and PropertyName parameter to all the GridColumns.

Blazor Bootstrap: Grid Component - Client side filtering
<Grid @ref="grid"
TItem="Employee4"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider"
AllowFiltering="true"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee4" HeaderText="Id" PropertyName="Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee4" HeaderText="Employee Name" PropertyName="Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee4" HeaderText="Designation" PropertyName="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee4" HeaderText="DOJ" PropertyName="DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee4" HeaderText="Active" PropertyName="IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee1> employees;

protected override void OnInitialized()
{
employees = new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
};
}

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
return await Task.FromResult(request.ApplyTo(employees));
}
}

See demo here

Client side filtering with string comparision

In the below example, StringComparision.Ordinal is used on the Employee Name column to make the filter case-sensitive.

info

By default, StringComparison.OrdinalIgnoreCase is used to compare culture-agnostic and case-insensitive string matching.

Blazor Bootstrap: Grid Component - Client side filtering with string comparision
<Grid TItem="Employee1"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider"
AllowFiltering="true"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name" StringComparison="StringComparison.Ordinal">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee1> employees;

protected override void OnInitialized()
{
employees = new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
};
}

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
return await Task.FromResult(request.ApplyTo(employees));
}
}

See demo here

Client side paging

For paging, AllowPaging and PageSize parameters are required. Add AllowPaging="true" and PageSize="20" parameters to the Grid. PageSize parameter is optional.

Blazor Bootstrap: Grid Component - Client side paging
INFO

The default page size is 10.

<Grid TItem="Employee1"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider"
AllowPaging="true"
PageSize="5"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee1> employees;

protected override void OnInitialized()
{
employees = new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), IsActive = true },
new Employee1 { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
new Employee1 { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), IsActive = true },
};
}

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
return await Task.FromResult(request.ApplyTo(employees));
}
}

See demo here

Client side sorting

For sorting, AllowSorting and SortKeySelector parameters are required. Add AllowSorting="true" parameter to Grid and SortKeySelector to all the GridColumns.

Blazor Bootstrap: Grid Component - Client side sorting
<Grid TItem="Employee1"
AllowSorting="true"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Employee Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Active" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee1> employees;

protected override void OnInitialized()
{
employees = new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
};
}

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
return await Task.FromResult(request.ApplyTo(employees));
}
}

See demo here

Client side filtering, paging, and sorting

Blazor Bootstrap: Grid Component - Client side filtering, paging, and sorting
<Grid TItem="Employee1"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider"
AllowFiltering="true"
AllowPaging="true"
PageSize="5"
AllowSorting="true"
AllowSelection="true"
SelectionMode="GridSelectionMode.Multiple"
SelectedItemsChanged="OnSelectedItemsChanged"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>

<div class="mt-3">
Selected Items Count: @selectedEmployees.Count
</div>

<div class="mt-2">
Selected Employees:
<ul>
@foreach (var emp in selectedEmployees)
{
<li>@emp.Name</li>
}
</ul>
</div>
@code {
private IEnumerable<Employee1> employees = default!;

private HashSet<Employee1> selectedEmployees = new();

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), IsActive = true },
new Employee1 { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
new Employee1 { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), IsActive = true },
};
}

private Task OnSelectedItemsChanged(HashSet<Employee1> employees)
{
selectedEmployees = employees is not null && employees.Any() ? employees : new();
return Task.CompletedTask;
}
}

See demo here

Set default filter

FilterOperator and FilterValue parameters are required to set the default filter.

Blazor Bootstrap: Grid Component - Set default filter
TIP

You can set the default filter on more than one GridColumn.

<Grid TItem="Employee1"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider"
AllowFiltering="true"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id" FilterOperator="FilterOperator.GreaterThanOrEquals" FilterValue="105">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee1>? employees;

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
};
}
}

See demo here

Disable specific column filter

Filterable parameter is required to disable the filter on a specific column. Add Filterable="false" parameter to GridColumn. The column filter is disabled on the Id column in the below example.

Blazor Bootstrap: Grid Component - Disable specific column filter
INFO

By default, Filterable="true" on all the columns if the AllowFiltering parameter is set to true on the grid.

<Grid TItem="Employee1"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider"
AllowFiltering="true"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" Filterable="false">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active" Filterable="false">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee1>? employees;

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
};
}
}

See demo here

Increase filter textbox width

Add FilterTextboxWidth parameter to the GridColumn to increase or decrease the filter textbox width, FilterTextboxWidth parameter is optional.

Blazor Bootstrap: Grid Component - Increase filter textbox width
NOTE

Filter textbox width measured in pixels.

<Grid TItem="Employee3"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider"
AllowFiltering="true"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee3" HeaderText="Id" PropertyName="Id" FilterTextboxWidth="80">
@context.Id
</GridColumn>
<GridColumn TItem="Employee3" HeaderText="First Name" PropertyName="FirstName" FilterTextboxWidth="80">
@context.FirstName
</GridColumn>
<GridColumn TItem="Employee3" HeaderText="Last Name" PropertyName="LastName" FilterTextboxWidth="80">
@context.LastName
</GridColumn>
<GridColumn TItem="Employee3" HeaderText="Email" PropertyName="Email">
@context.Email
</GridColumn>
<GridColumn TItem="Employee3" HeaderText="Company" TextNoWrap="true" PropertyName="Company">
@context.Company
</GridColumn>
<GridColumn TItem="Employee3" HeaderText="Designation" TextNoWrap="true" PropertyName="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee3" HeaderText="DOJ" PropertyName="DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee3" HeaderText="Salary" HeaderTextAlignment="Alignment.End" TextAlignment="Alignment.End" PropertyName="Salary" FilterTextboxWidth="80">
@context.Salary.ToString("N2")
</GridColumn>
<GridColumn TItem="Employee3" HeaderText="Active" HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center" PropertyName="IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee3>? employees;

private async Task<GridDataProviderResult<Employee3>> EmployeesDataProvider(GridDataProviderRequest<Employee3> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee3> GetEmployees()
{
return new List<Employee3>
{
new Employee3 { Id = 107, FirstName = "Alice", LastName = "Reddy", Email = "alice@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), Salary = 7700, IsActive = true },
new Employee3 { Id = 103, FirstName = "Bob", LastName = "Roy", Email = "bob@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), Salary = 19000, IsActive = true },
new Employee3 { Id = 106, FirstName = "John", LastName = "Papa", Email = "john@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), Salary = 12000, IsActive = true },
new Employee3 { Id = 104, FirstName = "Pop", LastName = "Two", Email = "pop@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), Salary = 19000, IsActive = false },
new Employee3 { Id = 105, FirstName = "Ronald", LastName = "Dire", Email = "ronald@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), Salary = 16500.50M, IsActive = true },
new Employee3 { Id = 102, FirstName = "Line", LastName = "K", Email = "line@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 24000, IsActive = true },
new Employee3 { Id = 101, FirstName = "Daniel", LastName = "Potter", Email = "daniel@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 21000, IsActive = true },
new Employee3 { Id = 108, FirstName = "Zayne", LastName = "Simmons", Email = "zayne@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), Salary = 17850, IsActive = true },
new Employee3 { Id = 109, FirstName = "Isha", LastName = "Davison", Email = "isha@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), Salary = 8000, IsActive = true },
};
}
}

See demo here

Server side filtering, paging and sorting

Blazor Bootstrap: Grid Component - Server side filtering, paging and sorting
NOTE

For server-side sorting, we need the SortString parameter on GridColumn along with the SortKeySelector parameter.

<Grid TItem="Customer2"
Class="table table-hover table-bordered table-striped"
DataProvider="CustomersDataProvider"
AllowFiltering="true"
AllowPaging="true"
AllowSorting="true"
Responsive="true">

<GridColumn TItem="Customer2" HeaderText="Id" PropertyName="CustomerId" SortString="CustomerId" SortKeySelector="item => item.CustomerId" FilterTextboxWidth="50" HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center">
@context.CustomerId
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Customer Name" PropertyName="CustomerName" SortString="CustomerName" SortKeySelector="item => item.CustomerName" FilterTextboxWidth="80">
@context.CustomerName
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Phone" PropertyName="Phone" SortString="Phone" SortKeySelector="item => item.Phone" FilterTextboxWidth="100">
@context.Phone
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Email" PropertyName="Email" SortString="Email" SortKeySelector="item => item.Email" FilterTextboxWidth="120">
@context.Email
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Address" PropertyName="Address" SortString="Address" SortKeySelector="item => item.Address" FilterTextboxWidth="150">
@context.Address
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Postal Zip" PropertyName="PostalZip" SortString="PostalZip" SortKeySelector="item => item.PostalZip" FilterTextboxWidth="80">
@context.PostalZip
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Country" PropertyName="Country" SortString="Country" SortKeySelector="item => item.Country" FilterTextboxWidth="80">
@context.Country
</GridColumn>

</Grid>
@code {
[Inject] public ICustomerService _customerService { get; set; } = default!;

private async Task<GridDataProviderResult<Customer2>> CustomersDataProvider(GridDataProviderRequest<Customer2> request)
{
string sortString = "";
SortDirection sortDirection = SortDirection.None;

if (request.Sorting is not null && request.Sorting.Any())
{
// Note: Multi column sorting is not supported at this moment
sortString = request.Sorting.FirstOrDefault()!.SortString;
sortDirection = request.Sorting.FirstOrDefault()!.SortDirection;
}
var result = await _customerService.GetCustomersAsync(request.Filters, request.PageNumber, request.PageSize, sortString, sortDirection, request.CancellationToken);
return await Task.FromResult(new GridDataProviderResult<Customer2> { Data = result.Item1, TotalCount = result.Item2 });
}
}

See demo here

Set default sorting

IsDefaultSortColumn parameter is required to set the default sorting. Add IsDefaultSortColumn="true" parameter to the GridColumn. The default sort direction will be ascending. To change the default sorting of a column, add SortDirection="SortDirection.Descending" to the GridColumn.

Blazor Bootstrap: Grid Component - Set default sorting
INFO

If more than one GridColumn has the IsDefaultSortColumn paramter, it will pick the first column as the default sorting column.

<Grid TItem="Employee1"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider"
AllowSorting="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" SortKeySelector="@(item => item.Id)">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name" SortKeySelector="@(item => item.Name)" IsDefaultSortColumn="true" SortDirection="SortDirection.Descending">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" SortKeySelector="@(item => item.Designation)">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" SortKeySelector="@(item => item.DOJ)">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active" SortKeySelector="@(item => item.IsActive)">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee1>? employees;

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
};
}
}

See demo here

Disable specific column sorting

Add Sortable="false" parameter the GridColumn to disable the sorting.

INFO

If sorting is disabled, then the SortKeySelector parameter is not required.

The sorting is disabled on the Designation column in the below example.

<Grid TItem="Employee1"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider"
AllowSorting="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" SortKeySelector="@(item => item.Id)">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name" SortKeySelector="@(item => item.Name)">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" Sortable="false">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" SortKeySelector="@(item => item.DOJ)">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active" SortKeySelector="@(item => item.IsActive)">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee1>? employees;

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
};
}
}

See demo here

Header text alignment

Use the HeaderTextAlignment parameter to change the header column alignment. By default, HeaderTextAlignment is set to Alignment.Start. Other options you can use are Alignment.Center and Alignment.End.

Blazor Bootstrap: Grid Component - Header text alignment
<Grid TItem="Employee1"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" HeaderTextAlignment="Alignment.Center">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" HeaderTextAlignment="Alignment.Center">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" HeaderTextAlignment="Alignment.Center">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active" HeaderTextAlignment="Alignment.End">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee1>? employees;

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
};
}
}

See demo here

Cell alignment

Use the TextAlignment parameter to change the cell data alignment. By default, TextAlignment is set to Alignment.Start. Other options you can use are Alignment.Center and Alignment.End.

Blazor Bootstrap: Grid Component - Cell alignment
<Grid TItem="Employee2"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider">

<GridColumns>
<GridColumn TItem="Employee2" HeaderText="Id" HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center">
@context.Id
</GridColumn>
<GridColumn TItem="Employee2" HeaderText="Employee Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee2" HeaderText="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee2" HeaderText="Salary" HeaderTextAlignment="Alignment.End" TextAlignment="Alignment.End">
@context.Salary
</GridColumn>
<GridColumn TItem="Employee2" HeaderText="Active" HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee2>? employees;

private async Task<GridDataProviderResult<Employee2>> EmployeesDataProvider(GridDataProviderRequest<Employee2> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee2> GetEmployees()
{
return new List<Employee2>
{
new Employee2 { Id = 107, Name = "Alice", Designation = "AI Engineer", Salary = 7700, IsActive = true },
new Employee2 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", Salary = 19000, IsActive = true },
new Employee2 { Id = 106, Name = "John", Designation = "Data Engineer", Salary = 12000, IsActive = true },
new Employee2 { Id = 104, Name = "Pop", Designation = "Associate Architect", Salary = 19000, IsActive = false },
new Employee2 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", Salary = 16500.50M, IsActive = true },
new Employee2 { Id = 102, Name = "Line", Designation = "Architect", Salary = 24000, IsActive = true },
new Employee2 { Id = 101, Name = "Daniel", Designation = "Architect", Salary = 21000, IsActive = true },
new Employee2 { Id = 108, Name = "Zayne", Designation = "Data Analyst", Salary = 17850, IsActive = true },
new Employee2 { Id = 109, Name = "Isha", Designation = "App Maker", Salary = 8000, IsActive = true },
};
}
}

See demo here

Cell formating

To format the cell data, use ToString() method and format strings. Refer: How to format numbers, dates, enums, and other types in .NET

Blazor Bootstrap: Grid Component - Cell formating
EXAMPLE

@context.Salary.ToString("N2")

<Grid TItem="Employee2" class="table table-hover table-bordered table-striped" DataProvider="EmployeesDataProvider">
<Grid TItem="Employee2"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider">

<GridColumns>
<GridColumn TItem="Employee2" HeaderText="Id" HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center">
@context.Id
</GridColumn>
<GridColumn TItem="Employee2" HeaderText="Employee Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee2" HeaderText="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee2" HeaderText="Salary" HeaderTextAlignment="Alignment.End" TextAlignment="Alignment.End">
@context.Salary.ToString("N2")
</GridColumn>
<GridColumn TItem="Employee2" HeaderText="Active" HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee2>? employees;

private async Task<GridDataProviderResult<Employee2>> EmployeesDataProvider(GridDataProviderRequest<Employee2> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee2> GetEmployees()
{
return new List<Employee2>
{
new Employee2 { Id = 107, Name = "Alice", Designation = "AI Engineer", Salary = 7700, IsActive = true },
new Employee2 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", Salary = 19000, IsActive = true },
new Employee2 { Id = 106, Name = "John", Designation = "Data Engineer", Salary = 12000, IsActive = true },
new Employee2 { Id = 104, Name = "Pop", Designation = "Associate Architect", Salary = 19000, IsActive = false },
new Employee2 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", Salary = 16500.50M, IsActive = true },
new Employee2 { Id = 102, Name = "Line", Designation = "Architect", Salary = 24000, IsActive = true },
new Employee2 { Id = 101, Name = "Daniel", Designation = "Architect", Salary = 21000, IsActive = true },
new Employee2 { Id = 108, Name = "Zayne", Designation = "Data Analyst", Salary = 17850, IsActive = true },
new Employee2 { Id = 109, Name = "Isha", Designation = "App Maker", Salary = 8000, IsActive = true },
};
}
}

See demo here

Cell nowrap

To prevent text from wrapping, add TextNoWrap="true" parameter to the GridColumn.

Blazor Bootstrap: Grid Component - Cell nowrap
TIP

Add Responsive="true" parameter to the grid to enable horizontal scrolling.

<Grid TItem="Employee3"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee3" HeaderText="Id" HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center">
@context.Id
</GridColumn>
<GridColumn TItem="Employee3" HeaderText="First Name">
@context.FirstName
</GridColumn>
<GridColumn TItem="Employee3" HeaderText="First Name">
@context.LastName
</GridColumn>
<GridColumn TItem="Employee3" HeaderText="Email">
@context.Email
</GridColumn>
<GridColumn TItem="Employee3" HeaderText="Company" TextNoWrap="true">
@context.Company
</GridColumn>
<GridColumn TItem="Employee3" HeaderText="Designation" TextNoWrap="true">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee3" HeaderText="DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee3" HeaderText="Salary" HeaderTextAlignment="Alignment.End" TextAlignment="Alignment.End">
@context.Salary.ToString("N2")
</GridColumn>
<GridColumn TItem="Employee3" HeaderText="Active" HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee3>? employees;

private async Task<GridDataProviderResult<Employee3>> EmployeesDataProvider(GridDataProviderRequest<Employee3> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee3> GetEmployees()
{
return new List<Employee3>
{
new Employee3 { Id = 107, FirstName = "Alice", LastName = "Reddy", Email = "alice@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), Salary = 7700, IsActive = true },
new Employee3 { Id = 103, FirstName = "Bob", LastName = "Roy", Email = "bob@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), Salary = 19000, IsActive = true },
new Employee3 { Id = 106, FirstName = "John", LastName = "Papa", Email = "john@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), Salary = 12000, IsActive = true },
new Employee3 { Id = 104, FirstName = "Pop", LastName = "Two", Email = "pop@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), Salary = 19000, IsActive = false },
new Employee3 { Id = 105, FirstName = "Ronald", LastName = "Dire", Email = "ronald@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), Salary = 16500.50M, IsActive = true },
new Employee3 { Id = 102, FirstName = "Line", LastName = "K", Email = "line@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 24000, IsActive = true },
new Employee3 { Id = 101, FirstName = "Daniel", LastName = "Potter", Email = "daniel@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 21000, IsActive = true },
new Employee3 { Id = 108, FirstName = "Zayne", LastName = "Simmons", Email = "zayne@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), Salary = 17850, IsActive = true },
new Employee3 { Id = 109, FirstName = "Isha", LastName = "Davison", Email = "isha@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), Salary = 8000, IsActive = true },
};
}
}

See demo here

Empty data

If there are no records to display in the Grid, by default, it will display the No records to display message. You can change this message by adding the EmptyText parameter to the Grid.

Blazor Bootstrap: Grid Component - Empty data
<Grid TItem="Employee"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider"
EmptyText="No records to display">

<GridColumns>
<GridColumn TItem="Employee" HeaderText="Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee" HeaderText="First Name">
@context.FirstName
</GridColumn>
<GridColumn TItem="Employee" HeaderText="Last Name">
@context.LastName
</GridColumn>
<GridColumn TItem="Employee" HeaderText="Designation">
@context.Designation
</GridColumn>
</GridColumns>

</Grid>
@code {
private async Task<GridDataProviderResult<Employee>> EmployeesDataProvider(GridDataProviderRequest<Employee> request)
{
await Task.Delay(3000);

return (new GridDataProviderResult<Employee> { Data = new List<Employee>(), TotalCount = 0 });
}
}

See demo here

Empty data template

Set the GridEmptyDataTemplate to customize the message displayed when the grid has no records.

Blazor Bootstrap: Grid Component - Empty data template
<Grid TItem="Employee"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider">

<GridColumns>
<GridColumn TItem="Employee" HeaderText="Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee" HeaderText="First Name">
@context.FirstName
</GridColumn>
<GridColumn TItem="Employee" HeaderText="Last Name">
@context.LastName
</GridColumn>
<GridColumn TItem="Employee" HeaderText="Designation">
@context.Designation
</GridColumn>
</GridColumns>

<GridTemplates>
<GridEmptyDataTemplate TItem="Employee">
<div class="text-center">
<svg clip-rule="evenodd" fill-rule="evenodd" height="128" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 64 64" width="128" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="fi_7486754"><linearGradient id="lg1"><stop offset="0" stop-color="#cadcf0"></stop><stop offset="1" stop-color="#a4bbdb"></stop></linearGradient><linearGradient id="_Linear1" gradientTransform="matrix(40 0 0 25.912 12 48.573)" gradientUnits="userSpaceOnUse" x1="0" x2="1" xlink:href="#lg1" y1="0" y2="0"></linearGradient><linearGradient id="lg2"><stop offset="0" stop-color="#a4bbdb"></stop><stop offset="1" stop-color="#8da3be"></stop></linearGradient><linearGradient id="_Linear2" gradientTransform="matrix(20.086 0 0 25.912 31.914 48.573)" gradientUnits="userSpaceOnUse" x1="0" x2="1" xlink:href="#lg2" y1="0" y2="0"></linearGradient><linearGradient id="lg3"><stop offset="0" stop-color="#e9f3fc"></stop><stop offset="1" stop-color="#cadcf0"></stop></linearGradient><linearGradient id="_Linear3" gradientTransform="matrix(14.679 14.768 -21.492 8.973 12.133 35.609)" gradientUnits="userSpaceOnUse" x1="0" x2="1" xlink:href="#lg3" y1="0" y2=".337"></linearGradient><linearGradient id="_Linear4" gradientTransform="matrix(25.743 1.634 -3.837 17.203 32.081 42.038)" gradientUnits="userSpaceOnUse" x1="0" x2="1" xlink:href="#lg3" y1="0" y2=".227"></linearGradient><linearGradient id="_Linear5" gradientTransform="matrix(20.007 -6.501 5.236 7.762 9.382 31.736)" gradientUnits="userSpaceOnUse" x1="0" x2="1" xlink:href="#lg3" y1="0" y2="-.619"></linearGradient><linearGradient id="_Linear6" gradientTransform="matrix(15.249 13.945 -20.61 7.651 37.354 21.357)" gradientUnits="userSpaceOnUse" x1="0" x2="1" xlink:href="#lg3" y1="0" y2=".429"></linearGradient><linearGradient id="_Linear7" gradientTransform="matrix(40 0 0 13 12 35.606)" gradientUnits="userSpaceOnUse" x1="0" x2="1" xlink:href="#lg1" y1="0" y2="0"></linearGradient><linearGradient id="_Linear8" gradientTransform="matrix(.431 16.153 -16.153 .431 34.048 28.815)" gradientUnits="userSpaceOnUse" x1="0" x2="1" xlink:href="#lg2" y1="0" y2="0"></linearGradient><linearGradient id="_Linear9" gradientTransform="matrix(19.724 23.273 -23.273 19.724 20.991 6.831)" gradientUnits="userSpaceOnUse" x1="0" x2="1" y1="0" y2="0"><stop offset="0" stop-color="#559aff"></stop><stop offset="1" stop-color="#2e69ef"></stop></linearGradient><linearGradient id="_Linear18" gradientTransform="matrix(6.695 0 0 4.448 30.933 4.607)" gradientUnits="userSpaceOnUse" x1="0" x2="1" xlink:href="#lg3" y1="0" y2="0"></linearGradient><linearGradient id="_Linear19" gradientTransform="matrix(6.695 0 0 -4.448 30.933 10.607)" gradientUnits="userSpaceOnUse" x1="0" x2="1" xlink:href="#lg3" y1="0" y2="0"></linearGradient><g id="Exp-3.-G"><path d="m52 35.617h-40v18.512c0 .883.579 1.662 1.425 1.916 4.019 1.205 15.321 4.596 18 5.4.375.112.775.112 1.15 0 2.679-.804 13.981-4.195 18-5.4.846-.254 1.425-1.033 1.425-1.916 0-4.636 0-18.512 0-18.512z" fill="url(#_Linear1)"></path><path d="m52 35.617h-20s-.194 25.912 0 25.912.387-.028.575-.084c2.679-.804 13.981-4.195 18-5.4.846-.254 1.425-1.033 1.425-1.916 0-4.636 0-18.512 0-18.512z" fill="url(#_Linear2)"></path><path d="m32 42.106-20-6.489s-3.507 5.2-5.075 7.524c-.176.261-.219.588-.117.885.103.297.338.528.637.626 3.799 1.234 15.045 4.888 17.995 5.846.423.138.887-.021 1.137-.39 1.341-1.979 5.423-8.002 5.423-8.002z" fill="url(#_Linear3)"></path><path d="m52 35.617-20 6.489s4.082 6.023 5.423 8.002c.25.369.714.528 1.137.39 2.95-.958 14.196-4.612 17.995-5.846.299-.098.534-.329.637-.626.102-.297.059-.624-.117-.885-1.568-2.324-5.075-7.524-5.075-7.524z" fill="url(#_Linear4)"></path><path d="m27.159 21.986c-.25-.367-.713-.526-1.136-.388-2.948.957-14.197 4.612-17.996 5.847-.299.097-.535.328-.637.625s-.059.625.117.885c1.444 2.142 4.493 6.662 4.493 6.662l20-6.511s-3.592-5.283-4.841-7.12z" fill="url(#_Linear5)"></path><path d="m56.493 28.955c.176-.26.219-.588.117-.885s-.338-.528-.637-.625c-3.799-1.235-15.048-4.89-17.996-5.847-.423-.138-.886.021-1.136.388-1.249 1.837-4.841 7.12-4.841 7.12l20 6.511s3.049-4.52 4.493-6.662z" fill="url(#_Linear6)"></path><path d="m52 35.617-20-6.511-20 6.511 20 6.489z" fill="url(#_Linear7)"></path><path d="m32 42.106v-13l-20 6.511z" fill="url(#_Linear8)"></path><g fill="url(#_Linear9)"><path d="m27.982 31.978c-.416-.272-.791-.563-1.124-.868-.406-.373-1.039-.346-1.413.061-.373.406-.346 1.039.061 1.412.409.376.87.734 1.382 1.069.462.302 1.082.172 1.384-.29s.172-1.082-.29-1.384z"></path><path d="m24.866 28.906c-.297-.403-.548-.808-.754-1.213-.25-.492-.853-.688-1.345-.438s-.688.853-.438 1.345c.254.498.562.997.927 1.492.327.444.953.539 1.398.212.444-.328.539-.954.212-1.398z"></path><path d="m23.404 24.825c.01-.403.069-.794.177-1.169.152-.53-.155-1.085-.686-1.237-.53-.152-1.085.155-1.237.686-.153.536-.239 1.095-.254 1.67-.013.552.423 1.011.975 1.024.552.014 1.011-.422 1.025-.974z"></path><path d="m24.942 21.485c.257-.238.545-.458.86-.657.467-.295.607-.913.313-1.379-.295-.467-.913-.607-1.38-.313-.423.267-.807.562-1.152.882-.405.375-.429 1.008-.054 1.413s1.008.429 1.413.054z"></path><path d="m28.661 19.76c.503-.093 1.036-.153 1.598-.176.552-.024.98-.491.957-1.042s-.49-.98-1.042-.957c-.66.028-1.286.099-1.877.208-.542.101-.902.623-.801 1.165.1.543.622.902 1.165.802z"></path><path d="m33.873 19.701c.853.01 1.647-.02 2.384-.085.55-.049.957-.535.908-1.085-.049-.549-.535-.956-1.085-.907-.675.059-1.402.087-2.184.077-.552-.006-1.005.437-1.011.988-.007.552.436 1.006.988 1.012z"></path><path d="m39.544 19.003c.99-.303 1.826-.691 2.526-1.136.465-.297.603-.915.306-1.381-.296-.465-.915-.603-1.381-.306-.563.358-1.238.666-2.036.91-.527.162-.825.721-.663 1.249.161.528.721.825 1.248.664z"></path><path d="m44.634 15.068c.472-.976.653-2.008.607-3.003-.026-.552-.495-.978-1.046-.952s-.978.494-.952 1.045c.032.676-.09 1.377-.41 2.04-.24.497-.032 1.096.465 1.336s1.096.031 1.336-.466z"></path><path d="m43.997 8.529c-.729-.985-1.718-1.671-2.796-1.892-.541-.11-1.07.238-1.181.779-.11.541.239 1.07.779 1.181.622.127 1.17.554 1.591 1.123.329.443.956.536 1.399.208.444-.329.537-.956.208-1.399z"></path></g><path d="m30.933 6.831c1.082-6.127 10.459-5.731 5 0z" fill="url(#_Linear18)"></path><path d="m30.933 8.383c1.082 6.126 10.459 5.731 5 0z" fill="url(#_Linear19)"></path><path d="m30.843 8.617h6.696c.552 0 1-.448 1-1s-.448-1-1-1h-6.696c-.551 0-1 .448-1 1s.449 1 1 1z" fill="url(#_Linear9)"></path></g></svg>
</div>
</GridEmptyDataTemplate>
</GridTemplates>

</Grid>
@code {
private async Task<GridDataProviderResult<Employee>> EmployeesDataProvider(GridDataProviderRequest<Employee> request)
{
await Task.Delay(3000);

return (new GridDataProviderResult<Employee> { Data = new List<Employee>(), TotalCount = 0 });
}
}

See demo here

Save and Load Grid Settings

This example shows how to save/load the Grid state. The state includes the page number, page size, and filters.

IMPORTANT

Saving the Grid's sorting state as part of GridSettings is not yet supported. This functionality will be included in future releases.

NOTE

Browser local storage is used to persist the Grid state. Common locations exist for persisting state are Server-side storage, URL, Browser storage, and In-memory state container service.

Blazor Bootstrap: Grid Component - Save and Load Grid Settings
@using System.Text.Json

<Grid @ref="grid"
TItem="Employee1"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider"
AllowFiltering="true"
PageSize="8"
AllowPaging="true"
AllowSorting="true"
Responsive="true"
GridSettingsChanged="OnGridSettingsChanged"
SettingsProvider="GridSettingsProvider">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id" SortKeySelector="item => item.Id" FilterOperator="FilterOperator.GreaterThanOrEquals" FilterValue="109">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
BlazorBootstrap.Grid<Employee1> grid = default!;
private IEnumerable<Employee1>? employees;

[Inject] public IJSRuntime JS { get; set; } = default!;

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private async Task OnGridSettingsChanged(GridSettings settings)
{
if (settings is null)
return;

// NOTE: enable below two lines, if you want to set default values for PageNumber and PageSize all the time.
//settings.PageNumber = 1;
//settings.PageSize = 10;

await JS.InvokeVoidAsync("window.localStorage.setItem", "grid-settings", JsonSerializer.Serialize(settings));
}

private async Task<GridSettings> GridSettingsProvider()
{
var settingsJson = await JS.InvokeAsync<string>("window.localStorage.getItem", "grid-settings");
if (string.IsNullOrWhiteSpace(settingsJson))
return null!;

var settings = JsonSerializer.Deserialize<GridSettings>(settingsJson);
if (settings is null)
return null!;

return settings;
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), IsActive = true },
new Employee1 { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
new Employee1 { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), IsActive = true },
};
}
}

See demo here

Data parameter - Assign collection

Assign a collection to the Data parameter to render the grid dynamically. The example below will render different department employees in the individual grid.

@using BlazorBootstrap.Demo.Models;

@foreach (var department in departments)
{
<p>@department.Name Employees:</p>
<Grid TItem="Employee1"
Class="table table-hover border-top"
Data="department.Employees">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
}
@code {
private List<Department> departments = new List<Department>()
{
new Department("Product 1 - Research & Development", new List<Employee1> {
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true }
}),
new Department("Product 2 - Research & Development", new List<Employee1> {
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true }
})
};
}

See demo here

Data parameter - Update collection

Assign a collection to the Data parameter to render the grid dynamically. The example below will render different department employees in the individual grid.

<Button Type="ButtonType.Button" Color="ButtonColor.Primary" @onclick="AddEmployee"> Add Employee </Button>
<Button Type="ButtonType.Button" Color="ButtonColor.Primary" @onclick="AddEmployee2"> Add Employee 2 </Button>

<Grid @ref="grid"
TItem="Employee1"
Class="table table-hover table-bordered table-striped mt-3"
Data="employees">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
Grid<Employee1> grid = default!;
private List<Employee1>? employees;

protected override void OnInitialized()
{
employees = new List<Employee1> {
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true }
};
}

private async Task AddEmployee()
{
// for the same employees collection, we are adding an object
// explicit grid refresh required
employees!.Add(CreateEmployee());
await grid.RefreshDataAsync();
}

private void AddEmployee2()
{
// creates a shallow copy
var emps = employees!.GetRange(0, employees.Count);
emps.Add(CreateEmployee());
// now employees variable has a new reference. So no need to refresh the grid explicitly
// explicit grid refresh is not required
employees = emps;
}

private Employee1 CreateEmployee()
{
var emp = new Employee1();
emp.Id = employees!.Max(x => x.Id) + 1;
emp.Name = $"Employee {emp.Id}";
emp.Designation = $"QA Engineer {emp.Id}";
emp.DOJ = new DateOnly(new Random().Next(1970, 2000), new Random().Next(1, 12), new Random().Next(1, 25));
emp.IsActive = true;
return emp;
}
}
note

The Add Employee button click adds a new employee to the existing employees collection—so explicit grid refresh is required.

The Add Employee 2 button click creates a shallow copy of the employees collection and adds a new employee. This new collection is assigned to the employees variable. Now, the employees variable has a new reference. So the grid will refresh automatically. An explicit grid refresh call is not required.

See demo here

Conditional css class for grid row

In the below example, we applied table-danger CSS class to the row where the employee is inactive and the table-success CSS class to the row where the employee designation is Architect.

Blazor Bootstrap: Grid Component - Conditional css class for grid row
<Grid TItem="Employee1"
Class="table table-hover table-bordered"
DataProvider="EmployeesDataProvider"
AllowFiltering="true"
AllowPaging="true"
PageSize="5"
AllowSorting="true"
Responsive="true"
RowClass="GetRowClass">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee1>? employees;

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private string GetRowClass(Employee1 emp)
{
if (!emp.IsActive)
return "table-danger";
else if (emp.Designation == "Architect")
return "table-success";

return string.Empty;
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), IsActive = true },
new Employee1 { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
new Employee1 { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), IsActive = true },
};
}
}

See demo here

Conditional css class for grid column

In the below example, we applied table-danger CSS class to the Active column where the employee is inactive and the table-success CSS class to the Active column where the employee is active.

Blazor Bootstrap: Grid Component - Conditional css class for grid column
<Grid TItem="Employee1"
Class="table table-hover table-bordered"
DataProvider="EmployeesDataProvider"
AllowFiltering="true"
AllowPaging="true"
PageSize="5"
AllowSorting="true"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1"
HeaderText="Active"
PropertyName="IsActive"
SortKeySelector="item => item.IsActive"
ColumnClass="@(x => x.IsActive ? "table-success" : "table-danger")">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee1> employees;

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), IsActive = true },
new Employee1 { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
new Employee1 { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), IsActive = true },
};
}
}

See demo here

Column class

In the following example, the Class parameter is used to apply the CSS class to an entire grid column, including the header.

Blazor Bootstrap: Grid Component - Column class
<Grid TItem="Employee1"
Class="table table-hover table-bordered"
DataProvider="EmployeesDataProvider"
AllowFiltering="true"
AllowPaging="true"
PageSize="5"
AllowSorting="true"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" Class="text-danger" HeaderText="Employee Name" PropertyName="Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee1>? employees;

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), IsActive = true },
new Employee1 { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
new Employee1 { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), IsActive = true },
};
}
}

See demo here

Custom column headers

In the below example, we use <HeaderContent> and <ChildContent> tags to define custom column header and cell content. When defining header content, filters and sorting are removed from column.

Blazor Bootstrap: Grid Component - Custom column headers
<Grid TItem="Employee1"
Class="table table-hover table-bordered"
DataProvider="EmployeesDataProvider"
AllowFiltering="true"
AllowPaging="true"
PageSize="5"
AllowSorting="true"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" PropertyName="IsActive" Filterable="false" Sortable="false">
<HeaderContent>
<Switch @bind-Value="IsAllChecked" />
</HeaderContent>
<ChildContent>
<Switch @bind-Value="@context.IsActive" />
</ChildContent>
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee1> employees = default!;

private bool IsAllChecked
{
get => employees?.All(e => e.IsActive) ?? false;
set => Array.ForEach(employees?.ToArray()!, e => e.IsActive = value);
}

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
Console.WriteLine("EmployeesDataProvider called...");

if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), IsActive = true },
new Employee1 { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
new Employee1 { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), IsActive = true },
};
}
}

See demo here

Selection

Set AllowSelection="true" to enable the selection on the Grid. By default, SelectionMode is Single.

Blazor Bootstrap: Grid Component - Selection
<Grid TItem="Employee1"
Class="table table-hover table-bordered"
DataProvider="EmployeesDataProvider"
AllowSelection="true"
SelectedItemsChanged="OnSelectedItemsChanged"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>

<div class="mt-3">
Selected Items Count: @selectedEmployees.Count
</div>

<div class="mt-2">
Selected Employees:
<ul>
@foreach (var emp in selectedEmployees)
{
<li>@emp.Name</li>
}
</ul>
</div>
@code {
private IEnumerable<Employee1> employees = default!;

private HashSet<Employee1> selectedEmployees = new();

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
Console.WriteLine("EmployeesDataProvider called...");

if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
};
}

private Task OnSelectedItemsChanged(HashSet<Employee1> employees)
{
selectedEmployees = employees is not null && employees.Any() ? employees : new();
return Task.CompletedTask;
}
}

See demo here

Multiple selection

To select multiple rows, set SelectionMode="GridSelectionMode.Multiple".

Blazor Bootstrap: Grid Component - Multiple selection
<Grid TItem="Employee1"
Class="table table-hover table-bordered"
DataProvider="EmployeesDataProvider"
AllowFiltering="true"
AllowSelection="true"
SelectionMode="GridSelectionMode.Multiple"
SelectedItemsChanged="OnSelectedItemsChanged"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>

<div class="mt-3">
Selected Items Count: @selectedEmployees.Count
</div>

<div class="mt-2">
Selected Employees:
<ul>
@foreach (var emp in selectedEmployees)
{
<li>@emp.Name</li>
}
</ul>
</div>
@code {
private IEnumerable<Employee1> employees = default!;

private HashSet<Employee1> selectedEmployees = new();

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
Console.WriteLine("EmployeesDataProvider called...");

if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
};
}

private Task OnSelectedItemsChanged(HashSet<Employee1> employees)
{
selectedEmployees = employees is not null && employees.Any() ? employees : new();
return Task.CompletedTask;
}
}
NOTE

Selected items are removed from the selection if they are not rendered after paging, sorting, filtering, etc.

See demo here

Disable selection

We can disable the header checkbox or row level checkbox based on a condition. For this, we have DisableAllRowsSelection and DisableRowSelection delegate parameters. In the below example, we disabled the header checkbox if any of the employee Id is less than 105. Also, disable check the row level checkbox if the employee Id is less than 105.

Blazor Bootstrap: Grid Component - Disable selection
<Grid TItem="Employee1"
Class="table table-hover table-bordered"
DataProvider="EmployeesDataProvider"
AllowSelection="true"
SelectionMode="GridSelectionMode.Multiple"
DisableAllRowsSelection="DisableAllRowsSelectionHandler"
DisableRowSelection="DisableRowSelectionHandler"
SelectedItemsChanged="OnSelectedItemsChanged"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>

<div class="mt-3">
Selected Items Count: @selectedEmployees.Count
</div>

<div class="mt-2">
Selected Employees:
<ul>
@foreach (var emp in selectedEmployees)
{
<li>@emp.Name</li>
}
</ul>
</div>
@code {
private IEnumerable<Employee1> employees = default!;

private HashSet<Employee1> selectedEmployees = new();

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
};
}

private bool DisableAllRowsSelectionHandler(IEnumerable<Employee1> employees)
{
return employees.Any(x => x.Id < 105); // disable selection if EmployeeId < 105
}

private bool DisableRowSelectionHandler(Employee1 emp)
{
return emp.Id < 105; // disable selection if EmployeeId < 105
}

private Task OnSelectedItemsChanged(HashSet<Employee1> employees)
{
selectedEmployees = employees is not null && employees.Any() ? employees : new();
return Task.CompletedTask;
}
}

See demo here

Change selected row background color

--bb-table-selected-row-color: rgba(0, 0, 0, 0.0725);
--bb-table-selected-row-background-color: rgba(0, 0, 0, 0.075);
--bb-table-selected-row-hover-color: #000;
--bb-table-selected-row-hover-background-color: rgba(0, 0, 0, 0.075);

These CSS variables are used to set the default colors and background color of a row when it's selected. You can override the --bb-table-selected-row-color, --bb-table-selected-row-background-color, --bb-table-selected-row-hover-color, and --bb-table-selected-row-hover-background-color variables in the application's specific CSS file to change the selected row's appearance. Please see the following example where the row text color is set to #fff (white) and the background color is set to #4c0bce (purple) when the row is selected.

Blazor Bootstrap: Grid Component - Change selected row background color
<Grid TItem="Employee1"
Class="table table-hover table-bordered"
Style="--bb-table-selected-row-color: #fff;--bb-table-selected-row-background-color: #4c0bce;--bb-table-selected-row-hover-color: #fff;--bb-table-selected-row-hover-background-color: #4c0bce;"
DataProvider="EmployeesDataProvider"
AllowFiltering="true"
AllowSelection="true"
SelectionMode="GridSelectionMode.Multiple"
SelectedItemsChanged="OnSelectedItemsChanged"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>

<div class="mt-3">
Selected Items Count: @selectedEmployees.Count
</div>

<div class="mt-2">
Selected Employees:
<ul>
@foreach (var emp in selectedEmployees)
{
<li>@emp.Name</li>
}
</ul>
</div>
@code {
private IEnumerable<Employee1> employees = default!;

private HashSet<Employee1> selectedEmployees = new();

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
Console.WriteLine("EmployeesDataProvider called...");

if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
};
}

private Task OnSelectedItemsChanged(HashSet<Employee1> employees)
{
selectedEmployees = employees is not null && employees.Any() ? employees : new();
return Task.CompletedTask;
}
}

Dynamic page size

Blazor Bootstrap: Grid Component - Dynamic page size
<Grid TItem="Employee1"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider"
AllowPaging="true"
PageSize="@pageSize"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>

<Button Type="ButtonType.Button" Color="ButtonColor.Primary" @onclick="() => ChangeSize(5)">Page Size 5</Button>
<Button Type="ButtonType.Button" Color="ButtonColor.Secondary" @onclick="() => ChangeSize(10)">Page Size 10</Button>
<Button Type="ButtonType.Button" Color="ButtonColor.Secondary" @onclick="() => ChangeSize(15)">Page Size 15</Button>
@code {
private int pageSize = 5;
private IEnumerable<Employee1> employees = default!;

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), IsActive = true },
new Employee1 { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
new Employee1 { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), IsActive = true },
};
}

private void ChangeSize(int size) => pageSize = size;
}

See demo here

Page size selection

Blazor Bootstrap: Grid Component - Page size selection
<Grid TItem="Employee1"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider"
AllowPaging="true"
PageSize="10"
PageSizeSelectorVisible="true"
PageSizeSelectorItems="@(new int[] { 5,10,20 })"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee1> employees = default!;

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), IsActive = true },
new Employee1 { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
new Employee1 { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), IsActive = true },
};
}
}

See demo here

Header row css class

Blazor Bootstrap: Grid Component - Header row css class
<Grid TItem="Employee1"
AllowSorting="true"
Class="table table-hover"
DataProvider="EmployeesDataProvider"
HeaderRowCssClass="bg-primary text-white border-bottom-0"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Employee Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Active" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>

<Grid TItem="Employee1"
AllowSorting="true"
Class="table table-hover"
DataProvider="EmployeesDataProvider"
HeaderRowCssClass="bg-primary text-white bg-opacity-75 border-bottom-0"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Employee Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Active" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>

<Grid TItem="Employee1"
AllowSorting="true"
Class="table table-hover"
DataProvider="EmployeesDataProvider"
HeaderRowCssClass="bg-success text-white border-bottom-0"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Employee Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Active" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>

<Grid TItem="Employee1"
AllowSorting="true"
Class="table table-hover"
DataProvider="EmployeesDataProvider"
HeaderRowCssClass="bg-success text-white bg-opacity-75 border-bottom-0"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Employee Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Active" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee1> employees = default!;

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
};
}
}

See demo here

Filters row css class

Blazor Bootstrap: Grid Component - Filters row css class
<Grid TItem="Employee1"
AllowFiltering="true"
AllowSorting="true"
Class="table table-hover"
DataProvider="EmployeesDataProvider"
FiltersRowCssClass="bg-primary text-white bg-opacity-25 border-bottom-0"
HeaderRowCssClass="bg-primary text-white border-bottom-0"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>

<Grid TItem="Employee1"
AllowFiltering="true"
AllowSorting="true"
Class="table table-hover"
DataProvider="EmployeesDataProvider"
HeaderRowCssClass="bg-warning text-white border-bottom-0"
FiltersRowCssClass="bg-warning text-white bg-opacity-25 border-bottom-0"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>

<Grid TItem="Employee1"
AllowFiltering="true"
AllowSorting="true"
Class="table table-hover"
DataProvider="EmployeesDataProvider"
HeaderRowCssClass="bg-danger text-white border-bottom-0"
FiltersRowCssClass="bg-danger text-white bg-opacity-25 border-bottom-0"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>

<Grid TItem="Employee1"
AllowFiltering="true"
AllowSorting="true"
Class="table table-hover"
DataProvider="EmployeesDataProvider"
HeaderRowCssClass="bg-success text-white border-bottom-0"
FiltersRowCssClass="bg-success text-white bg-opacity-25 border-bottom-0"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>

<Grid TItem="Employee1"
AllowFiltering="true"
AllowSorting="true"
Class="table table-hover"
DataProvider="EmployeesDataProvider"
HeaderRowCssClass="bg-info text-white border-bottom-0"
FiltersRowCssClass="bg-info text-white bg-opacity-25 border-bottom-0"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>

<Grid TItem="Employee1"
AllowFiltering="true"
AllowSorting="true"
Class="table table-hover"
DataProvider="EmployeesDataProvider"
HeaderRowCssClass="bg-dark text-white border-bottom-0"
FiltersRowCssClass="bg-dark text-white bg-opacity-25 border-bottom-0"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>

<Grid TItem="Employee1"
AllowFiltering="true"
AllowSorting="true"
Class="table table-hover"
DataProvider="EmployeesDataProvider"
HeaderRowCssClass="bg-secondary text-white border-bottom-0"
FiltersRowCssClass="bg-secondary text-white bg-opacity-25 border-bottom-0"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee1> employees = default!;

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
};
}
}

See demo here

Row click event

<Grid TItem="Employee1"
AllowRowClick="true"
AllowSorting="true"
Class="table table-hover"
DataProvider="EmployeesDataProvider"
HeaderRowCssClass="bg-primary text-white border-bottom-0"
OnRowClick="OnRowClick"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Employee Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Active" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
[Inject] ModalService ModalService { get; set; } = default!;

private IEnumerable<Employee1> employees = default!;

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
};
}

private async Task OnRowClick(GridRowEventArgs<Employee1> args)
{
await ModalService.ShowAsync(new ModalOption { Type = ModalType.Primary, Title = "Event: Row Click", Message = $"Id: {args.Item.Id}, Name: {args.Item.Name}" });
}
}

See demo here

Row double click event

<Grid TItem="Employee1"
AllowRowClick="true"
AllowSorting="true"
Class="table table-hover"
DataProvider="EmployeesDataProvider"
HeaderRowCssClass="bg-danger text-white border-bottom-0"
OnRowDoubleClick="OnRowDoubleClick"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Employee Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>

<GridColumn TItem="Employee1" HeaderText="Active" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
[Inject] ModalService ModalService { get; set; } = default!;

private IEnumerable<Employee1> employees = default!;

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
};
}

private async Task OnRowDoubleClick(GridRowEventArgs<Employee1> args)
{
await ModalService.ShowAsync(new ModalOption { Type = ModalType.Primary, Title = "Event: Row Double Click", Message = $"Id: {args.Item.Id}, Name: {args.Item.Name}" });
}
}

See demo here

Translations

In the example below, you will see translations related to pagination and filters in Dutch.

Blazor Bootstrap: Grid Component - Translations
<Grid TItem="User"
AllowFiltering="true"
AllowPaging="true"
AllowSorting="true"
Class="table table-hover"
DataProvider="UsersDataProvider"
FiltersRowCssClass="bg-dark text-white bg-opacity-25 border-bottom-0"
FiltersTranslationProvider="GridFiltersTranslationProvider"
HeaderRowCssClass="bg-dark text-white border-bottom-0"
PageSize="10"
PageSizeSelectorVisible="true"
PageSizeSelectorItems="@(new int[] { 5,10,20 })"
PaginationItemsTextFormat="{0} - {1} van {2} artikelen"
ItemsPerPageText="Artikelen per pagina"
EnumFilterSelectText="Selecteer"
Responsive="true">

<GridColumns>
<GridColumn TItem="User" HeaderText="Id" PropertyName="Id">
@context.Id
</GridColumn>
<GridColumn TItem="User" HeaderText="User Name" PropertyName="Name">
@context.Name
</GridColumn>
<GridColumn TItem="User" HeaderText="DOB" PropertyName="DOB">
@context.DOB
</GridColumn>
<GridColumn TItem="User" HeaderText="Status" PropertyName="Status" FilterTextboxWidth="170">
@context.Status
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<User> users = default!;

private async Task<IEnumerable<FilterOperatorInfo>> GridFiltersTranslationProvider()
{
var filtersTranslation = new List<FilterOperatorInfo>();

// number/date/boolean
filtersTranslation.Add(new("=", "gelijk aan", FilterOperator.Equals));
filtersTranslation.Add(new("!=", "Niet gelijk", FilterOperator.NotEquals));
// number/date
filtersTranslation.Add(new("<", "Minder dan", FilterOperator.LessThan));
filtersTranslation.Add(new("<=", "Kleiner dan of gelijk aan", FilterOperator.LessThanOrEquals));
filtersTranslation.Add(new(">", "Groter dan", FilterOperator.GreaterThan));
filtersTranslation.Add(new(">=", "Groter dan of gelijk aan", FilterOperator.GreaterThanOrEquals));
// string
filtersTranslation.Add(new("*a*", "Bevat", FilterOperator.Contains));
filtersTranslation.Add(new("a**", "Begint met", FilterOperator.StartsWith));
filtersTranslation.Add(new("**a", "Eindigt met", FilterOperator.EndsWith));
filtersTranslation.Add(new("=", "gelijk aan", FilterOperator.Equals));
// common
filtersTranslation.Add(new("x", "Duidelijk", FilterOperator.Clear));

return await Task.FromResult(filtersTranslation);
}


private async Task<GridDataProviderResult<User>> UsersDataProvider(GridDataProviderRequest<User> request)
{
if (users is null) // pull employees only one time for client-side filtering, sorting, and paging
users = GetUsers(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(users));
}

private IEnumerable<User> GetUsers()
{
return new List<User>
{
new User { Id = 107, Name = "Alice", DOB = new DateOnly(1998, 11, 17), Status = UserStatus.Registered },
new User { Id = null, Name = "Bob", DOB = new DateOnly(1985, 1, 5), Status = UserStatus.Verified },
new User { Id = 106, Name = "John", DOB = new DateOnly(1995, 4, 17), Status = UserStatus.Registered },
new User { Id = 104, Name = "Pop", DOB = new DateOnly(1985, 6, 8), Status = UserStatus.Registered },
new User { Id = 105, Name = "Ronald", DOB = new DateOnly(1991, 8, 23), Status = UserStatus.VerificationPending },
new User { Id = 102, Name = "Line", DOB = new DateOnly(1977, 1, 12), Status = UserStatus.VerificationPending },
new User { Id = 101, Name = "Daniel", DOB = new DateOnly(1977, 1, 12), Status = UserStatus.Registered },
new User { Id = 108, Name = "Zayne", DOB = new DateOnly(1991, 1, 1), Status = UserStatus.Verified },
new User { Id = 109, Name = "Isha", DOB = null, Status = UserStatus.Verified },
new User { Id = 110, Name = "Vijay", DOB = new DateOnly(1990, 7, 1), Status = UserStatus.Verified },
};
}

public record class User
{
public int? Id { get; set; }
public string? Name { get; set; }
public DateOnly? DOB { get; set; }
public UserStatus Status { get; set; }
}

public enum UserStatus
{
Registered,
VerificationPending,
Verified
}
}

See demo here

Fixed header

To set the fixed header, set the FixedHeader parameter to true. The minimum height of the grid is 320 pixels. You can change the units to em, pt, px, or etc. by setting the Unit parameter.

Blazor Bootstrap: Grid Component - Fixed header
<Grid @ref="grid"
TItem="Employee4"
Class="table table-hover table-bordered"
DataProvider="EmployeesDataProvider"
FixedHeader="true"
Height="350"
Responsive="true"
Unit="Unit.Px">

<GridColumns>
<GridColumn TItem="Employee4" HeaderText="Id" PropertyName="Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee4" HeaderText="Employee Name" PropertyName="Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee4" HeaderText="Designation" PropertyName="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee4" HeaderText="Designation" PropertyName="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee4" HeaderText="Designation" PropertyName="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee4" HeaderText="Designation" PropertyName="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee4" HeaderText="DOJ" PropertyName="DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee4" HeaderText="Active" PropertyName="IsActive">
@context.IsActive
</GridColumn>
<GridColumn TItem="Employee4" HeaderText="Active" PropertyName="IsActive">
@context.IsActive
</GridColumn>
<GridColumn TItem="Employee4" HeaderText="Active" PropertyName="IsActive">
@context.IsActive
</GridColumn>
<GridColumn TItem="Employee4" HeaderText="Active" PropertyName="IsActive">
@context.IsActive
</GridColumn>
<GridColumn TItem="Employee4" HeaderText="Active" PropertyName="IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
BlazorBootstrap.Grid<Employee4> grid = default!;
private IEnumerable<Employee4> employees = default!;

protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
}

private async Task<GridDataProviderResult<Employee4>> EmployeesDataProvider(GridDataProviderRequest<Employee4> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee4> GetEmployees()
{
return new List<Employee4>
{
new Employee4 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee4 { Id = null, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee4 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee4 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee4 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee4 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee4 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee4 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee4 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = null, IsActive = true },
new Employee4 { Id = 110, Name = "Vijay", Designation = null, DOJ = new DateOnly(1990, 7, 1), IsActive = true },
};
}
}

See demo here

Fixed header with filters

Blazor Bootstrap: Grid Component - Fixed header with filters
<Grid TItem="Customer2"
Class="table table-hover table-bordered"
DataProvider="CustomersDataProvider"
AllowFiltering="true"
AllowPaging="true"
AllowSorting="true"
FixedHeader="true"
Responsive="true"
Unit="Unit.Px">

<GridColumns>
<GridColumn TItem="Customer2" HeaderText="Id" PropertyName="CustomerId" SortString="CustomerId" SortKeySelector="item => item.CustomerId" FilterTextboxWidth="50" HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center">
@context.CustomerId
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Customer Name" PropertyName="CustomerName" SortString="CustomerName" SortKeySelector="item => item.CustomerName" FilterTextboxWidth="80">
@context.CustomerName
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Phone" PropertyName="Phone" SortString="Phone" SortKeySelector="item => item.Phone" FilterTextboxWidth="100">
@context.Phone
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Email" PropertyName="Email" SortString="Email" SortKeySelector="item => item.Email" FilterTextboxWidth="120">
@context.Email
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Address" PropertyName="Address" SortString="Address" SortKeySelector="item => item.Address" FilterTextboxWidth="150">
@context.Address
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Postal Zip" PropertyName="PostalZip" SortString="PostalZip" SortKeySelector="item => item.PostalZip" FilterTextboxWidth="80">
@context.PostalZip
</GridColumn>
<GridColumn TItem="Customer2" FreezeRightPosition="0" HeaderText="Country" PropertyName="Country" SortString="Country" SortKeySelector="item => item.Country" FilterTextboxWidth="80">
@context.Country
</GridColumn>
</GridColumns>

</Grid>
@code {
[Inject] public ICustomerService _customerService { get; set; } = default!;

private async Task<GridDataProviderResult<Customer2>> CustomersDataProvider(GridDataProviderRequest<Customer2> request)
{
string sortString = "";
SortDirection sortDirection = SortDirection.None;

if (request.Sorting is not null && request.Sorting.Any())
{
// Note: Multi column sorting is not supported at this moment
sortString = request.Sorting.FirstOrDefault().SortString;
sortDirection = request.Sorting.FirstOrDefault().SortDirection;
}
var result = await _customerService.GetCustomersAsync(request.Filters, request.PageNumber, request.PageSize, sortString, sortDirection, request.CancellationToken);
return await Task.FromResult(new GridDataProviderResult<Customer2> { Data = result.Item1, TotalCount = result.Item2 });
}
}

See demo here

Freeze columns

Blazor Bootstrap: Grid Component - Freeze columns
<Grid TItem="Customer2"
Class="table table-hover table-bordered text-nowrap"
DataProvider="CustomersDataProvider"
AllowPaging="true"
AllowSorting="true"
Responsive="true"
Unit="Unit.Px">

<GridColumns>
<GridColumn TItem="Customer2" Freeze="true" FreezeLeftPosition="0" HeaderText="Id" PropertyName="CustomerId" SortString="CustomerId" SortKeySelector="item => item.CustomerId" FilterTextboxWidth="50" HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center">
@context.CustomerId
</GridColumn>
<GridColumn TItem="Customer2" Freeze="true" FreezeLeftPosition="54.98" HeaderText="Customer Name" PropertyName="CustomerName" SortString="CustomerName" SortKeySelector="item => item.CustomerName" FilterTextboxWidth="80">
@context.CustomerName
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Phone" PropertyName="Phone" SortString="Phone" SortKeySelector="item => item.Phone" FilterTextboxWidth="100">
@context.Phone
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Email" PropertyName="Email" SortString="Email" SortKeySelector="item => item.Email" FilterTextboxWidth="120">
@context.Email
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Address" PropertyName="Address" SortString="Address" SortKeySelector="item => item.Address" FilterTextboxWidth="150">
@context.Address
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Postal Zip" PropertyName="PostalZip" SortString="PostalZip" SortKeySelector="item => item.PostalZip" FilterTextboxWidth="80">
@context.PostalZip
</GridColumn>
<GridColumn TItem="Customer2" Freeze="true" FreezeDirection="FreezeDirection.Right" FreezeRightPosition="0" HeaderText="Country" PropertyName="Country" SortString="Country" SortKeySelector="item => item.Country" FilterTextboxWidth="80">
@context.Country
</GridColumn>
</GridColumns>

</Grid>
@code {
[Inject] public ICustomerService _customerService { get; set; } = default!;

private async Task<GridDataProviderResult<Customer2>> CustomersDataProvider(GridDataProviderRequest<Customer2> request)
{
string sortString = "";
SortDirection sortDirection = SortDirection.None;

if (request.Sorting is not null && request.Sorting.Any())
{
// Note: Multi column sorting is not supported at this moment
sortString = request.Sorting.FirstOrDefault().SortString;
sortDirection = request.Sorting.FirstOrDefault().SortDirection;
}
var result = await _customerService.GetCustomersAsync(request.Filters, request.PageNumber, request.PageSize, sortString, sortDirection, request.CancellationToken);
return await Task.FromResult(new GridDataProviderResult<Customer2> { Data = result.Item1, TotalCount = result.Item2 });
}
}

See demo here

Freeze columns with fixed header

Blazor Bootstrap: Grid Component - Freeze columns with fixed header
<Grid TItem="Customer2"
Class="table table-hover table-bordered text-nowrap"
DataProvider="CustomersDataProvider"
AllowPaging="true"
AllowSorting="true"
FixedHeader="true"
Responsive="true"
Unit="Unit.Px">

<GridColumns>
<GridColumn TItem="Customer2" Freeze="true" FreezeLeftPosition="0" HeaderText="Id" PropertyName="CustomerId" SortString="CustomerId" SortKeySelector="item => item.CustomerId" FilterTextboxWidth="50" HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center">
@context.CustomerId
</GridColumn>
<GridColumn TItem="Customer2" Freeze="true" FreezeLeftPosition="54.98" HeaderText="Customer Name" PropertyName="CustomerName" SortString="CustomerName" SortKeySelector="item => item.CustomerName" FilterTextboxWidth="80">
@context.CustomerName
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Phone" PropertyName="Phone" SortString="Phone" SortKeySelector="item => item.Phone" FilterTextboxWidth="100">
@context.Phone
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Email" PropertyName="Email" SortString="Email" SortKeySelector="item => item.Email" FilterTextboxWidth="120">
@context.Email
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Address" PropertyName="Address" SortString="Address" SortKeySelector="item => item.Address" FilterTextboxWidth="150">
@context.Address
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Postal Zip" PropertyName="PostalZip" SortString="PostalZip" SortKeySelector="item => item.PostalZip" FilterTextboxWidth="80">
@context.PostalZip
</GridColumn>
<GridColumn TItem="Customer2" Freeze="true" FreezeDirection="FreezeDirection.Right" FreezeRightPosition="0" HeaderText="Country" PropertyName="Country" SortString="Country" SortKeySelector="item => item.Country" FilterTextboxWidth="80">
@context.Country
</GridColumn>
</GridColumns>

</Grid>
@code {
[Inject] public ICustomerService _customerService { get; set; } = default!;

private async Task<GridDataProviderResult<Customer2>> CustomersDataProvider(GridDataProviderRequest<Customer2> request)
{
string sortString = "";
SortDirection sortDirection = SortDirection.None;

if (request.Sorting is not null && request.Sorting.Any())
{
// Note: Multi column sorting is not supported at this moment
sortString = request.Sorting.FirstOrDefault().SortString;
sortDirection = request.Sorting.FirstOrDefault().SortDirection;
}
var result = await _customerService.GetCustomersAsync(request.Filters, request.PageNumber, request.PageSize, sortString, sortDirection, request.CancellationToken);
return await Task.FromResult(new GridDataProviderResult<Customer2> { Data = result.Item1, TotalCount = result.Item2 });
}
}

See demo here

Freeze columns with fixed header and filters

Blazor Bootstrap: Grid Component - Freeze columns with fixed header and filters
<Grid TItem="Customer2"
Class="table table-hover table-bordered text-nowrap"
DataProvider="CustomersDataProvider"
AllowFiltering="true"
AllowPaging="true"
AllowSorting="true"
FixedHeader="true"
Responsive="true"
Unit="Unit.Px">

<GridColumns>
<GridColumn TItem="Customer2" Freeze="true" FreezeLeftPosition="0" HeaderText="Id" PropertyName="CustomerId" SortString="CustomerId" SortKeySelector="item => item.CustomerId" FilterTextboxWidth="50" HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center">
@context.CustomerId
</GridColumn>
<GridColumn TItem="Customer2" Freeze="true" FreezeLeftPosition="130.35" HeaderText="Customer Name" PropertyName="CustomerName" SortString="CustomerName" SortKeySelector="item => item.CustomerName" FilterTextboxWidth="80">
@context.CustomerName
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Phone" PropertyName="Phone" SortString="Phone" SortKeySelector="item => item.Phone" FilterTextboxWidth="100">
@context.Phone
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Email" PropertyName="Email" SortString="Email" SortKeySelector="item => item.Email" FilterTextboxWidth="120">
@context.Email
</GridColumn>
<GridColumn TItem="Customer2" HeaderText="Address" PropertyName="Address" SortString="Address" SortKeySelector="item => item.Address" FilterTextboxWidth="150">
@context.Address
</GridColumn>
<GridColumn TItem="Customer2" Freeze="true" FreezeDirection="FreezeDirection.Right" FreezeRightPosition="171" HeaderText="Postal Zip" PropertyName="PostalZip" SortString="PostalZip" SortKeySelector="item => item.PostalZip" FilterTextboxWidth="80">
@context.PostalZip
</GridColumn>
<GridColumn TItem="Customer2" Freeze="true" FreezeDirection="FreezeDirection.Right" FreezeRightPosition="0" HeaderText="Country" PropertyName="Country" SortString="Country" SortKeySelector="item => item.Country" FilterTextboxWidth="80">
@context.Country
</GridColumn>
</GridColumns>

</Grid>
@code {
[Inject] public ICustomerService _customerService { get; set; } = default!;

private async Task<GridDataProviderResult<Customer2>> CustomersDataProvider(GridDataProviderRequest<Customer2> request)
{
string sortString = "";
SortDirection sortDirection = SortDirection.None;

if (request.Sorting is not null && request.Sorting.Any())
{
// Note: Multi column sorting is not supported at this moment
sortString = request.Sorting.FirstOrDefault().SortString;
sortDirection = request.Sorting.FirstOrDefault().SortDirection;
}
var result = await _customerService.GetCustomersAsync(request.Filters, request.PageNumber, request.PageSize, sortString, sortDirection, request.CancellationToken);
return await Task.FromResult(new GridDataProviderResult<Customer2> { Data = result.Item1, TotalCount = result.Item2 });
}
}

See demo here

Auto hide paging

Automatically hides the paging controls when the grid item count is less than or equal to the PageSize and this property is set to true.

Blazor Bootstrap: Grid Component - Auto hide paging
<Grid TItem="Employee1"
AllowFiltering="true"
AllowPaging="true"
AllowSorting="true"
AutoHidePaging="true"
Class="table table-hover table-bordered table-striped"
DataProvider="EmployeesDataProvider"
PageSize="10"
PageSizeSelectorVisible="true"
PageSizeSelectorItems="@(new int[] { 5,10,20 })"
Responsive="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation" SortKeySelector="item => item.Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ" SortKeySelector="item => item.DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

</Grid>
@code {
private IEnumerable<Employee1> employees = default!;

private async Task<GridDataProviderResult<Employee1>> EmployeesDataProvider(GridDataProviderRequest<Employee1> request)
{
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
employees = GetEmployees(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(employees));
}

private IEnumerable<Employee1> GetEmployees()
{
return new List<Employee1>
{
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true },
new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true },
new Employee1 { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), IsActive = true },
new Employee1 { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), IsActive = true },
new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true },
new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true },
new Employee1 { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), IsActive = true },
};
}
}

See demo here

Enum filter

Blazor Bootstrap: Grid Component - Enum filter
<Grid @ref="grid"
TItem="User"
Class="table table-hover table-bordered table-striped"
DataProvider="UsersDataProvider"
AllowFiltering="true"
Responsive="true">

<GridColumns>
<GridColumn TItem="User" HeaderText="Id" PropertyName="Id">
@context.Id
</GridColumn>
<GridColumn TItem="User" HeaderText="User Name" PropertyName="Name">
@context.Name
</GridColumn>
<GridColumn TItem="User" HeaderText="DOB" PropertyName="DOB">
@context.DOB
</GridColumn>
<GridColumn TItem="User" HeaderText="Status" PropertyName="Status" FilterTextboxWidth="170">
@context.Status
</GridColumn>
</GridColumns>

</Grid>
@code {
BlazorBootstrap.Grid<User> grid = default!;
private IEnumerable<User> users = default!;

protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
}

private async Task<GridDataProviderResult<User>> UsersDataProvider(GridDataProviderRequest<User> request)
{
if (users is null) // pull employees only one time for client-side filtering, sorting, and paging
users = GetUsers(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(users));
}

private IEnumerable<User> GetUsers()
{
return new List<User>
{
new User { Id = 107, Name = "Alice", DOB = new DateOnly(1998, 11, 17), Status = UserStatus.Registered },
new User { Id = null, Name = "Bob", DOB = new DateOnly(1985, 1, 5), Status = UserStatus.Verified },
new User { Id = 106, Name = "John", DOB = new DateOnly(1995, 4, 17), Status = UserStatus.Registered },
new User { Id = 104, Name = "Pop", DOB = new DateOnly(1985, 6, 8), Status = UserStatus.Registered },
new User { Id = 105, Name = "Ronald", DOB = new DateOnly(1991, 8, 23), Status = UserStatus.VerificationPending },
new User { Id = 102, Name = "Line", DOB = new DateOnly(1977, 1, 12), Status = UserStatus.VerificationPending },
new User { Id = 101, Name = "Daniel", DOB = new DateOnly(1977, 1, 12), Status = UserStatus.Registered },
new User { Id = 108, Name = "Zayne", DOB = new DateOnly(1991, 1, 1), Status = UserStatus.Verified },
new User { Id = 109, Name = "Isha", DOB = null, Status = UserStatus.Verified },
new User { Id = 110, Name = "Vijay", DOB = new DateOnly(1990, 7, 1), Status = UserStatus.Verified },
};
}

public record class User
{
public int? Id { get; set; }
public string? Name { get; set; }
public DateOnly? DOB { get; set; }
public UserStatus Status { get; set; }
}

public enum UserStatus
{
Registered,
VerificationPending,
Verified
}
}

See demo here

Guid filter

Blazor Bootstrap: Grid Component - Guid filter
<Grid @ref="grid"
TItem="User"
Class="table table-hover table-bordered table-striped"
DataProvider="UsersDataProvider"
AllowFiltering="true"
Responsive="true">

<GridColumns>
<GridColumn TItem="User" HeaderText="Oid" PropertyName="Oid" FilterTextboxWidth="240">
@context.Oid
</GridColumn>
<GridColumn TItem="User" HeaderText="Id" PropertyName="Id" FilterTextboxWidth="70">
@context.Id
</GridColumn>
<GridColumn TItem="User" HeaderText="User Name" PropertyName="Name" FilterTextboxWidth="100">
@context.Name
</GridColumn>
<GridColumn TItem="User" HeaderText="DOB" PropertyName="DOB">
@context.DOB
</GridColumn>
<GridColumn TItem="User" HeaderText="Status" PropertyName="Status" FilterTextboxWidth="170">
@context.Status
</GridColumn>
</GridColumns>

</Grid>
@code {
BlazorBootstrap.Grid<User> grid = default!;
private IEnumerable<User> users = default!;

protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
}

private async Task<GridDataProviderResult<User>> UsersDataProvider(GridDataProviderRequest<User> request)
{
if (users is null) // pull employees only one time for client-side filtering, sorting, and paging
users = GetUsers(); // call a service or an API to pull the employees

return await Task.FromResult(request.ApplyTo(users));
}

private IEnumerable<User> GetUsers()
{
return new List<User>
{
new User { Oid = Guid.NewGuid(), Id = 107, Name = "Alice", DOB = new DateOnly(1998, 11, 17), Status = UserStatus.Registered },
new User { Oid = Guid.NewGuid(), Id = null, Name = "Bob", DOB = new DateOnly(1985, 1, 5), Status = UserStatus.Verified },
new User { Oid = Guid.NewGuid(), Id = 106, Name = "John", DOB = new DateOnly(1995, 4, 17), Status = UserStatus.Registered },
new User { Oid = Guid.NewGuid(), Id = 104, Name = "Pop", DOB = new DateOnly(1985, 6, 8), Status = UserStatus.Registered },
new User { Oid = Guid.NewGuid(), Id = 105, Name = "Ronald", DOB = new DateOnly(1991, 8, 23), Status = UserStatus.VerificationPending },
new User { Oid = Guid.NewGuid(), Id = 102, Name = "Line", DOB = new DateOnly(1977, 1, 12), Status = UserStatus.VerificationPending },
new User { Oid = Guid.NewGuid(), Id = 101, Name = "Daniel", DOB = new DateOnly(1977, 1, 12), Status = UserStatus.Registered },
new User { Oid = Guid.NewGuid(), Id = 108, Name = "Zayne", DOB = new DateOnly(1991, 1, 1), Status = UserStatus.Verified },
new User { Oid = Guid.NewGuid(), Id = 109, Name = "Isha", DOB = null, Status = UserStatus.Verified },
new User { Oid = Guid.NewGuid(), Id = 110, Name = "Vijay", DOB = new DateOnly(1990, 7, 1), Status = UserStatus.Verified },
};
}

public record class User
{
public Guid Oid { get; set; }
public int? Id { get; set; }
public string? Name { get; set; }
public DateOnly? DOB { get; set; }
public UserStatus Status { get; set; }
}

public enum UserStatus
{
Registered,
VerificationPending,
Verified
}
}

See demo here

Detail View

To enable detail view, set the AllowDetailView parameter to true. In the following example, existing <GridColumn> tags are nested under <GridColumns> tag to distinguish them from <GridDetailView>.

Blazor Bootstrap: Grid Component - Detail View
<Grid TItem="Product"
Class="table table-hover border-top"
Data="products"
AllowDetailView="true"
AllowSorting="true">

<GridColumns>
<GridColumn TItem="Product" HeaderText="Id" PropertyName="Id" SortKeySelector="item => item.Id">
@context.Id
</GridColumn>
<GridColumn TItem="Product" HeaderText="Employee Name" PropertyName="Name" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>
<GridColumn TItem="Product" HeaderText="Active" PropertyName="IsActive" SortKeySelector="item => item.IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

<GridDetailView TItem="Product">

<Grid TItem="Ingredient"
Class="table table-hover border-top"
Data="GetIngredients(context.Id)">

<GridColumns>
<GridColumn TItem="Ingredient" Context="emp1" HeaderText="Id" PropertyName="Id">
@emp1.Id
</GridColumn>
<GridColumn TItem="Ingredient" Context="emp1" HeaderText="Description" PropertyName="Description">
@emp1.Description
</GridColumn>
<GridColumn TItem="Ingredient" Context="emp1" HeaderText="Unit" PropertyName="Unit">
@emp1.Unit
</GridColumn>
<GridColumn TItem="Ingredient" Context="emp1" HeaderText="Quantity" PropertyName="Quantity">
@emp1.Quantity
</GridColumn>
</GridColumns>

</Grid>

</GridDetailView>

</Grid>
@code {
private List<Product> products = new List<Product> {
new Product { Id = 10, Name = "Product 10", IsActive = true },
new Product { Id = 20, Name = "Product 20", IsActive = true },
new Product { Id = 30, Name = "Product 30", IsActive = true },
new Product { Id = 40, Name = "Product 40", IsActive = true },
new Product { Id = 50, Name = "Product 50", IsActive = true }
};

private List<Ingredient> ingredients = new List<Ingredient> {
new Ingredient { Id = 10105, ProductId = 10, Description = "Ingredient 1", Unit = "UNIT1", Quantity = 350 },
new Ingredient { Id = 10106, ProductId = 10, Description = "Ingredient 2", Unit = "UNIT1", Quantity = 600 },
new Ingredient { Id = 10107, ProductId = 10, Description = "Ingredient 3", Unit = "UNIT2", Quantity = 13 },
new Ingredient { Id = 10108, ProductId = 10, Description = "Ingredient 4", Unit = "UNIT3", Quantity = 25 },
new Ingredient { Id = 20109, ProductId = 20, Description = "Ingredient 5", Unit = "UNIT1", Quantity = 750 },
new Ingredient { Id = 20110, ProductId = 20, Description = "Ingredient 3", Unit = "UNIT2", Quantity = 13 },
new Ingredient { Id = 10111, ProductId = 10, Description = "Ingredient 4", Unit = "UNIT3", Quantity = 25 },
new Ingredient { Id = 20112, ProductId = 20, Description = "Ingredient 5", Unit = "UNIT1", Quantity = 750 },
new Ingredient { Id = 40113, ProductId = 40, Description = "Ingredient 3", Unit = "UNIT2", Quantity = 13 },
new Ingredient { Id = 50114, ProductId = 50, Description = "Ingredient 4", Unit = "UNIT3", Quantity = 25 },
new Ingredient { Id = 20115, ProductId = 20, Description = "Ingredient 5", Unit = "UNIT1", Quantity = 750 },
};

private IEnumerable<Ingredient> GetIngredients(int productId) => ingredients.Where(i => i.ProductId == productId);

public record class Product
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsActive { get; set; }
}

public record class Ingredient
{
public int Id { get; set; }
public int ProductId { get; set; }
public string? Description { get; set; }
public string? Unit { get; set; }
public int Quantity { get; set; }
}
}

See demo here

Nested Grid

To create a nested grid, we first need to enable the detail view. To enable the detail view, set the AllowDetailView parameter to true. In the following example, existing <GridColumn> tags are nested under <GridColumns> tag to distinguish them from <GridDetailView>.

Blazor Bootstrap: Grid Component - Detail View
<Grid TItem="Employee1"
Class="table table-hover border-top"
Data="employees"
AllowDetailView="true">

<GridColumns>
<GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id">
@context.Id
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name">
@context.Name
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation">
@context.Designation
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ">
@context.DOJ
</GridColumn>
<GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive">
@context.IsActive
</GridColumn>
</GridColumns>

<GridDetailView TItem="Employee1">
<Grid TItem="Employee1"
Class="table table-hover border-top"
Data="employees"
AllowDetailView="true">

<GridColumns>
<GridColumn TItem="Employee1" Context="emp1" HeaderText="Id" PropertyName="Id">
@emp1.Id
</GridColumn>
<GridColumn TItem="Employee1" Context="emp1" HeaderText="Employee Name" PropertyName="Name">
@emp1.Name
</GridColumn>
<GridColumn TItem="Employee1" Context="emp1" HeaderText="Designation" PropertyName="Designation">
@emp1.Designation
</GridColumn>
<GridColumn TItem="Employee1" Context="emp1" HeaderText="DOJ" PropertyName="DOJ">
@emp1.DOJ
</GridColumn>
<GridColumn TItem="Employee1" Context="emp1" HeaderText="Active" PropertyName="IsActive">
@emp1.IsActive
</GridColumn>
</GridColumns>

<GridDetailView TItem="Employee1" Context="emp1">
<div class="row">
<div class="col-2 fw-bold">Id</div>
<div class="col">@emp1.Id</div>
</div>
<div class="row">
<div class="col-2 fw-bold">Name</div>
<div class="col">@emp1.Name</div>
</div>
<div class="row">
<div class="col-2 fw-bold">Designation</div>
<div class="col">@emp1.Designation</div>
</div>
<div class="row">
<div class="col-2 fw-bold">DOJ</div>
<div class="col">@emp1.DOJ</div>
</div>
<div class="row">
<div class="col-2 fw-bold">IsActive</div>
<div class="col">@emp1.IsActive</div>
</div>
</GridDetailView>

</Grid>

</GridDetailView>
</Grid>
@code {
private List<Employee1> employees = new List<Employee1> {
new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true },
new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true },
new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true },
new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false },
new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true }
};

public record class Employee1
{
public int Id { get; set; }
public string? Name { get; set; }
public string? Designation { get; set; }
public DateOnly DOJ { get; set; }
public bool IsActive { get; set; }
}
}

See demo here