DataTable component for Blazor

DataTable for Blazor

I have just released a new DataTable component for Blazor WebAssembly and Blazor Server. The NuGet package is available here. The source code will be available soon on GitHub.

This component supports client/server side paging, filtering and sorting.

DataTable in action

DataTable in action - DataTable component for Blazor
DataTable in action

Installation

So, first install the package from NuGet or execute this command

dotnet add package PSC.Blazor.Components.DataTable

or

PM> Install-Package PSC.Blazor.Components.DataTable

Then, open your index.html or _Host.cshtml and add the CSS

<link href="/_content/PSC.Blazor.Components.DataTable/css/DataTable.css" rel="stylesheet" />

in the head of the page and then the script at the bottom of the page

<script src="/_content/PSC.Blazor.Components.DataTable/js/DataTable.js"></script>

Then, add in your _Imports.razor file the following using:

@using PSC.Blazor.Components.DataTable
@using PSC.Blazor.Components.DataTable.Enums
@using PSC.Blazor.Components.DataTable.Models
@using PSC.Blazor.Components.DataTable.EventsArgs

Also, in the project you should have added some libraries to see the DataTable well:

Anatomy of DataTable

DataTable basis
DataTable basis
Loading data
Loading data
DataTable column in details
Filters autogenerated
Filters autogenerated

DataTable properties

NameTypeDefaultDescription
ItemsIListListThe list of items to display
UsePagingboolfalseBoolean indicating whether to use paging or not
UsePageSizeSelectorbooltrueBoolean indicating hether to show the page size dropdown list (10, 25, 50 records)
PageNumberint1The number of the current page (only applicable when property UsePaging is true)
PageSizeint10The amount of items shown on a page (only applicable when property UsePaging is true)
PageCountint1The total amount of pages (only applicable when property UsePaging is true)
FetchDataFunc<RequestArgs, Task>?nullThe method used for fetching and manipulating data (paging, filtering, sorting) on the server. When this method is null, all these actions will be performed on the initial dataset on the client.
ShowHeaderFiltersbooltrueIndicates whether or not to show the header/grid filters
AllowRowSelectionboolfalseIndicates whether or not it’s possible to select a row
RowClickedEventEventCallbacknullThe callback for when a row is clicked (only applicable when property AllowRowSelection is true)
SelectedItemTModelnullThe selected item
SelectedItemCssClassstringbg-infoThe css class for the selected row
EmptyGridTextstring“No records to show”The text to show when the Items list is empty
IsLoadingboolfalseIndicates whether or not data is being fetched, used to show a spinner
Idstring“”The html identifier of the table tag
ContainerCssClassstring“table-responsive”The css class for the container/parent tag of the table
CssClassstring“table”The css class for the table tag
ApplyButtonCssClassstring“”The css class for the “apply” buttons on grid/header filters
InputCssClassstring“”The css class for the input tags in the grid/header filters
StylesTableStyle [Enum FLAGS]nullThe style flags used for the table
TableAttributesDictionary<string, object>?nullAny custom attributes for the table tag (see Blazor docs for more info)
RowAttributesDictionary<string, object>?nullAny custom attributes for the rows (see Blazor docs for more info)
ContainerHeightint300The height of the table container in pixels
ContainerHeightUnitCssUnitCssUnit.PxThe unit of the container height
IncludeAdvancedFiltersbooltrueIndicates whether to allow advanced filtering or not
IncludeHeaderFiltersboolfalseIndicates whether or not to include grid/header filters
IncludeSearchButtonboolfalseIndicates whether or not to include a search icon. When clicked filters, sorting and paging is performed on the server is FetchData has a value otherwise it happens on the client
IncludeToggleFiltersboolfalseIndicates whether or not to include a toggle icon. When clicked header/grid filters will re or disappear (only applicable when property
SearchOnApplyHeaderFilterbooltrueIndicates whether or not a search is instantly triggered when a header/grid filter is applied
AutoAddFilterWhenClickedAndNoneActivebooltrueIndicates whether or not to add an empty filter rule when a filterable column is clicked an no other filter rules exist.
ItemHeightint?nullThe pixel height of a an item (tr) in the grid. Customize this to get better virtualization.

DataTableColumn properties

NameTypeDefaultDescription
PropertyExpression<Func?nullThe selector of a field/property of TModel to use for the column
IsSortableboolfalseIndicates whether or not sorting is enabled for this column
IsFilterableboolfalseIndicates whether or not filtering is enabled for this column
IsResizableboolfalseIndicates whether the column is resizable
IsVisiblebooltrueIndicates whether the column should be rendered
CustomTitlestringnullThe name of the column header (by default the name of the property is used)
HeaderTemplateRenderFragment<string>nullThe template to use for the grid header, the string is the name of the column
Idstring“”The html identifier of the table tag
ContainerCssClassstring“table-responsive”The css class for the container/parent tag of the table
CssClassstring“table”The css class for the table tag
IsDefaultSortColumnboolfalseIndicates whether or not this column is sorted on by default
DefaultSortDirectionSortDirection [Enum]SortDirection.AscendingThe sort direction of the default sorting column
TextAlignmentTextAlignment [Enum]TextAlignment.LeftThe text alignment for the column
VerticalAlignmentVerticalAlignment [Enum]VerticalAlignment.BottomThe vertical alignment for the column
StylesTableStyle [Enum FLAGS]nullThe style flags used for the table
AttributesDictionary<string, object>?nullAny custom attributes for the table tag (see Blazor docs for more info)
HeaderFilterAttributesDictionary<string, object>?nullAny custom attributes for the header inputs
ContainerHeightint300The height of the table container in pixels
MinWidthHeaderint10The height of the table container in the set units (default vw)
MinWidthHeaderUnitCssUnitCssUnit.VwThe unit of the minWidthHeader property
IncludeHeaderFilterboolfalseIndicates whether or not to add header/grid filters
IncludeSearchButtonboolfalseIndicates whether or not to include a search icon. When clicked filters, sorting and paging is performed on the server is FetchData has a value otherwise it happens on the client
IncludeToggleFiltersboolfalseIndicates whether or not to include a toggle icon. When clicked header/grid filters will re or disappear (only applicable when property
SearchOnApplyHeaderFilterboolfalseIndicates whether or not a search is instantly triggered when a header/grid filter is applied
AutoAddFilterWhenClickedAndNoneActivebooltrueIndicates whether or not to add an empty filter rule when a filterable column is clicked an no other filter rules exist.
RowTemplateRenderFragment?nullThe custom render fragment to use for the column
RowAttributesDictionary<string, object>?nullAny custom attributes for the rows (see Blazor docs for more info)
ContainerHeightint300The height of the table container in pixels
MaxWidthint100The max width in pixels of a column
MaxWidthUnitCssUnitCssUnit.PxThe unit of the MaxWidth property
DateTimeFormatDateTimeFormatDateTimeFormat.DateThe DateTimeFormat to use in header/grid filters
IsHeaderVisiblebooltrueIndicates whether the column is visible or not
IncludeAdvancedFiltersboolfalseIndicates whether to allow advanced filtering or not
IncludeSearchButtonboolfalseIndicates whether or not to include a search icon. When clicked filters, sorting and paging is performed on the server is FetchData has a value otherwise it happens on the client
IncludeToggleFiltersboolfalseIndicates whether or not to include a toggle icon. When clicked header/grid filters will re or disappear (only applicable when property
SearchOnApplyHeaderFilterboolfalseIndicates whether or not a search is instantly triggered when a header/grid filter is applied
AutoAddFilterWhenClickedAndNoneActivebooltrueIndicates whether or not to add an empty filter rule when a filterable column is clicked an no other filter rules exist.

Basic table

<DataTable TModel="WeatherForecast"
           Items="forecasts">
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.Date" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.TemperatureC"
                    CustomTitle="Celsius" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.TemperatureF"
                    CustomTitle="Fahrenheit" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.MyNullableInt" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.Summary" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.Country" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.UpdatedRecently"
                    CustomTitle="Recently updated" />
</DataTable>
Basic example - DataTable component for Blazor
Basic example

Custom template

<DataTable TModel="WeatherForecast"
           Items="forecasts">
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.Date" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.TemperatureC"
                    CustomTitle="Celsius" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.TemperatureF"
                    CustomTitle="Fahrenheit" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.MyNullableInt" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.Summary" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.Country" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.UpdatedRecently"
                    CustomTitle="Recently updated">
    <Template Context="forecast">
        @if (forecast.UpdatedRecently)
        {
            <i class="fas fa-check-circle" style="color: green;" />
        }
        else
        {
            <i class="far fa-times-circle" style="color: red;" />
        }
            </Template>
    </DataTableColumn>
</DataTable>
Custom row - DataTable component for Blazor
Custom row

Sorting

<DataTable TModel="WeatherForecast"
           Items="forecasts">
    <DataTableColumn TModel="WeatherForecast"
                    IsSortable="true"
                    Property="(e) => e.Date" />
    <DataTableColumn TModel="WeatherForecast"
                    IsSortable="true"
                    Property="(e) => e.TemperatureC"
                    CustomTitle="Celsius" />
    <DataTableColumn TModel="WeatherForecast"
                    IsSortable="true"
                    Property="(e) => e.TemperatureF"
                    CustomTitle="Fahrenheit" />
    <DataTableColumn TModel="WeatherForecast"
                    IsSortable="true"
                    Property="(e) => e.MyNullableInt" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.Summary" />
    <DataTableColumn TModel="WeatherForecast"
                    IsSortable="true"
                    Property="(e) => e.Country" />
    <DataTableColumn TModel="WeatherForecast"
                    IsSortable="true"
                    Property="(e) => e.UpdatedRecently"
                    CustomTitle="Recently updated" />
</DataTable>

Pagination

<DataTable TModel="WeatherForecast"
           Items="forecasts"
           UsePaging="true">
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.Date" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.TemperatureC"
                    CustomTitle="Celsius" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.TemperatureF"
                    CustomTitle="Fahrenheit" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.MyNullableInt" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.Summary" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.Country" />
    <DataTableColumn TModel="WeatherForecast"
                    Property="(e) => e.UpdatedRecently"
                    CustomTitle="Recently updated" />
</DataTable>
Pagination example
Pagination example

Filtering

<DataTable TModel="WeatherForecast"
           Items="forecasts">
    <DataTableColumn TModel="WeatherForecast"
                    IsFilterable="true"
                    Property="(e) => e.Date" />
    <DataTableColumn TModel="WeatherForecast"
                    IsFilterable="true"
                    Property="(e) => e.TemperatureC"
                    CustomTitle="Celsius" />
    <DataTableColumn TModel="WeatherForecast"
                    IsFilterable="true"
                    Property="(e) => e.TemperatureF"
                    CustomTitle="Fahrenheit" />
    <DataTableColumn TModel="WeatherForecast"
                    IsFilterable="true"
                    Property="(e) => e.MyNullableInt" />
    <DataTableColumn TModel="WeatherForecast"
                    IsFilterable="true"
                    Property="(e) => e.Summary" />
    <DataTableColumn TModel="WeatherForecast"
                    IsFilterable="true"
                    Property="(e) => e.Country" />
    <DataTableColumn TModel="WeatherForecast"
                    IsFilterable="true"
                    Property="(e) => e.UpdatedRecently"
                    CustomTitle="Recently updated" />
</DataTable>
Advance filtering
Advance filtering
Filter popup (automatically generated)
Filter popup (automatically generated)

Header/Grid filters

<DataTable TModel="WeatherForecast"
           Items="forecasts"
           SearchOnApplyHeaderFilter="true">
    <DataTableColumn TModel="WeatherForecast"
                    IsFilterable="true"
                    IncludeHeaderFilter="true"
                    Property="(e) => e.Date" />
    <DataTableColumn TModel="WeatherForecast"
                    IsFilterable="true"
                    IncludeHeaderFilter="true"
                    Property="(e) => e.TemperatureC"
                    CustomTitle="Celsius" />
    <DataTableColumn TModel="WeatherForecast"
                    IsFilterable="true"
                    IncludeHeaderFilter="true"
                    Property="(e) => e.TemperatureF"
                    CustomTitle="Fahrenheit" />
    <DataTableColumn TModel="WeatherForecast"
                    IsFilterable="true"
                    IncludeHeaderFilter="true"
                    Property="(e) => e.MyNullableInt" />
    <DataTableColumn TModel="WeatherForecast"
                    IsFilterable="true"
                    IncludeHeaderFilter="true"
                    Property="(e) => e.Summary" />
    <DataTableColumn TModel="WeatherForecast"
                    IsFilterable="true"
                    IncludeHeaderFilter="true"
                    Property="(e) => e.Country" />
    <DataTableColumn TModel="WeatherForecast"
                    IsFilterable="true"
                    IncludeHeaderFilter="true"
                    Property="(e) => e.UpdatedRecently"
                    CustomTitle="Recently updated" />
</DataTable>
Header filters
Header filters

Server side support

<DataTable TModel="WeatherForecast"
           Items="pagedForecasts.Data"
           UsePaging="true"
           FetchData="DoFetchData"
           PageCount="@pagedForecasts.Paging.PageCount"
           PageSize="@pagedForecasts.Paging.PageSize">
    <DataTableColumn TModel="WeatherForecast"
                    IsSortable="true"
                    IsFilterable="true"
                    Property="(e) => e.Date" />
    <DataTableColumn TModel="WeatherForecast"
                    IsSortable="true"
                    IsFilterable="true"
                    Property="(e) => e.TemperatureC"
                    CustomTitle="Celsius" />
    <DataTableColumn TModel="WeatherForecast"
                    IsSortable="true"
                    IsFilterable="true"
                    Property="(e) => e.TemperatureF"
                    CustomTitle="Fahrenheit" />
    <DataTableColumn TModel="WeatherForecast"
                    IsSortable="true"
                    IsFilterable="true"
                    Property="(e) => e.MyNullableInt" />
    <DataTableColumn TModel="WeatherForecast"
                    IsSortable="true"
                    IsFilterable="true"
                    Property="(e) => e.Summary" />
    <DataTableColumn TModel="WeatherForecast"
                    IsSortable="true"
                    IsFilterable="true"
                    Property="(e) => e.Country" />
    <DataTableColumn TModel="WeatherForecast"
                    IsSortable="true"
                    IsFilterable="true"
                    Property="(e) => e.UpdatedRecently"
                    CustomTitle="Recently updated" />
</DataTable>

// Method will be called by the DataTable when necessary
private async Task DoFetchData(RequestArgs<WeatherForecast> args)
{
    pagedForecasts = await ForecastService.SearchForecastAsync(args);
    // Don't forget to call StateHasChanged() since your component is the owner of the DataTable
    StateHasChanged();
}

// ForecastService:
public async Task SearchForecastAsync(RequestArgs<WeatherForecast> args)
{
    IQueryable<WeatherForecast> result = context.Forecasts.AsQueryable();

    // RequestArgs contains all the information about sorting, paging and filtering
    foreach (var filter in args.AppliedFilters)
    {
        // Filters can easily be translated into expressions, 
        // or use the filtering info to create your own filtering solution
        result = result.Where(filter.GenerateExpression());
    }

    // Use the Core.Utils to easily apply paging and sorting
    // Or use the paging info in RequestArgs to build your own paging solution
    pagedResult = Utils.ApplyPaging(result, pager);

    return Task.FromResult(pagedResult);
}

Support bootstrap table styles

<DataTable TModel="WeatherForecast" Items="forecasts" Styles="TableStyle.Sm">
....
</DataTable>
<DataTable TModel="WeatherForecast" Items="forecasts" Styles="TableStyle.Bordered">
....
</DataTable>
<DataTable TModel="WeatherForecast" Items="forecasts" Styles="TableStyle.Borderless">
....
</DataTable>
<DataTable TModel="WeatherForecast" Items="forecasts" Styles="TableStyle.Dark">
....
</DataTable>
<DataTable TModel="WeatherForecast" Items="forecasts" Styles="TableStyle.Hover">
....
</DataTable>
<DataTable TModel="WeatherForecast" Items="forecasts" Styles="TableStyle.Striped">
....
</DataTable>
DataTable Bootstrap style
DataTable Bootstrap style
DataTable Bootstrap style

Alignment

<DataTable TModel="WeatherForecast"
           Items="forecasts">
    <DataTableColumn TModel="WeatherForecast"
                    TextAlignment="Core.Models.TextAlignment.Center"
                    IsSortable="true"
                    Property="(e) => e.Date" />
    <DataTableColumn TModel="WeatherForecast"
                    TextAlignment="Core.Models.TextAlignment.End"
                    IsSortable="true"
                    Property="(e) => e.TemperatureC"
                    CustomTitle="Celsius" />
    <DataTableColumn TModel="WeatherForecast"
                    TextAlignment="Core.Models.TextAlignment.Left"
                    IsSortable="true"
                    Property="(e) => e.TemperatureF"
                    CustomTitle="Fahrenheit" />
    <DataTableColumn TModel="WeatherForecast"
                    TextAlignment="Core.Models.TextAlignment.Right"
                    IsSortable="true"
                    Property="(e) => e.MyNullableInt" />
    <DataTableColumn TModel="WeatherForecast"
                    TextAlignment="Core.Models.TextAlignment.Start"
                    IsSortable="true"
                    Property="(e) => e.Summary" />
</DataTable>

DataTable on YouTube

More examples and documentation

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.