
Filter and sort function
Filter to quickly find the data you want to see; sort to quickly find or compare data.
- Filters a column of data to specify the column to be filtered by specifying the
filterable
property of the column - Sort a column of data, specify the column to be sorted by specifying the
Sortable
property of the column, change the collation by multiple clicks
Set the Filterable
property of the TableColumn
column to control whether the column header has data filtering enabled
Demo
Filterable
currently supports two applications:
- The
Filters
in the query method parameters are filter criteria, and the database can filter the data by itself through this property when querying data - No sense of use, normal query data, no processing is done to filtering, internal processing will be carried out according to
Filter
- When external filtering has been made, set the
Value of the IsFiltered
property of theQueryData<TItem>
parameter totrue
- Each column can be set separately, and the filter between columns is
And
and relationship
of DateTime, string, bool, enum, int type, and
the pop-up filter box is also differentFilterable
value of TableColumn
to true
, no additional code required@inject IStringLocalizer<Foo> FooLocalizer
<div>
<Table TItem="Foo"
IsPagination="true" PageItemsSource="@PageItemsSource"
IsStriped="true" IsBordered="true" IsMultipleSelect="true"
ShowSkeleton="true"
OnQueryAsync="@OnQueryAsync">
<TableColumns>
<TableColumn @bind-Field="@context.DateTime" Width="180" Sortable="true" Filterable="true" />
<TableColumn @bind-Field="@context.Name" Width="100" Sortable="true" Filterable="true" />
<TableColumn @bind-Field="@context.Address" Sortable="true" Filterable="true" />
<TableColumn @bind-Field="@context.Complete" Width="100" Sortable="true" Filterable="true" />
<TableColumn @bind-Field="@context.Education" Width="100" Sortable="true" Filterable="true" />
<TableColumn @bind-Field="@context.Count" Width="100" Sortable="true" Filterable="true" />
</TableColumns>
</Table>
</div>
@code {
/// <summary>
/// Foo 类为Demo测试用,如有需要请自行下载源码查阅
/// Foo class is used for Demo test, please download the source code if necessary
/// https://gitee.com/LongbowEnterprise/BootstrapBlazor/blob/main/src/BootstrapBlazor.Shared/Data/Foo.cs
/// </summary>
[NotNull]
private List<Foo>? Items { get; set; }
private static IEnumerable<int> PageItemsSource => new int[] { 4, 10, 20 };
/// <summary>
/// OnInitialized 方法
/// </summary>
protected override void OnInitialized()
{
base.OnInitialized();
Items = Foo.GenerateFoo(FooLocalizer);
}
private Task<QueryData<Foo>> OnQueryAsync(QueryPageOptions options)
{
IEnumerable<Foo> items = Items;
// 过滤
var isFiltered = false;
if (options.Filters.Any())
{
items = items.Where(options.Filters.GetFilterFunc<Foo>());
isFiltered = true;
}
// 排序
var isSorted = false;
// 此段代码可不写,组件内部自行处理
if (options.SortName == nameof(Foo.DateTime) && options.SortList != null)
{
var sortInvoker = Utility.GetSortListFunc<Foo>();
items = sortInvoker(items, options.SortList);
isSorted = true;
}
else if (!string.IsNullOrEmpty(options.SortName))
{
// 外部未进行排序,内部自动进行排序处理
var invoker = Utility.GetSortFunc<Foo>();
items = invoker(items, options.SortName, options.SortOrder);
isSorted = true;
}
// 设置记录总数
var total = items.Count();
// 内存分页
items = items.Skip((options.PageIndex - 1) * options.PageItems).Take(options.PageItems).ToList();
return Task.FromResult(new QueryData<Foo>()
{
Items = items,
TotalCount = total,
IsSorted = isSorted,
IsFiltered = isFiltered
});
}
}
Set FilterTemplate
template values, customize column filter templates, very suitable for complex types of filter pop-ups
Demo
The FilterTemplate
type is RenderFragment
: its value is a custom component, and the component must inherit the filterBase
In this case, the last column in this case, the Quantity column, uses the custom component by filtering the template CustomerFilter
[portal] CustomerFilter component source code
@using BootstrapBlazor.Shared.Samples.Table
@inject IStringLocalizer<TablesFilterTemplate> Localizer
@inject IStringLocalizer<Foo> FooLocalizer
@inject IOptionsMonitor<WebsiteOptions> WebsiteOption
<div>
<p>@((MarkupString)Localizer["TablesFilterTemplateDescription", ComponentSourceCodeUrl].Value)</p>
<Table TItem="Foo"
IsPagination="true" PageItemsSource="@PageItemsSource"
IsStriped="true" IsBordered="true" IsMultipleSelect="true"
ShowSkeleton="true"
OnQueryAsync="@OnQueryAsync">
<TableColumns>
<TableColumn @bind-Field="@context.DateTime" Width="180" Sortable="true" Filterable="true"/>
<TableColumn @bind-Field="@context.Name" Width="100" Sortable="true" Filterable="true"/>
<TableColumn @bind-Field="@context.Address" Sortable="true" Filterable="true"/>
<TableColumn @bind-Field="@context.Complete" Width="100" Sortable="true" Filterable="true">
<Template Context="value">
<Checkbox Value="@value.Value" IsDisabled="true"></Checkbox>
</Template>
</TableColumn>
<TableColumn @bind-Field="@context.Count" Width="100" Sortable="true" Filterable="true">
<FilterTemplate>
<CustomerFilter></CustomerFilter>
</FilterTemplate>
</TableColumn>
</TableColumns>
</Table>
</div>
@code {
/// <summary>
/// Foo 类为Demo测试用,如有需要请自行下载源码查阅
/// Foo class is used for Demo test, please download the source code if necessary
/// https://gitee.com/LongbowEnterprise/BootstrapBlazor/blob/main/src/BootstrapBlazor.Shared/Data/Foo.cs
/// </summary>
[NotNull]
private List<Foo>? Items { get; set; }
private static IEnumerable<int> PageItemsSource => new int[] { 4, 10, 20 };
private string ComponentSourceCodeUrl => $"{WebsiteOption.CurrentValue.BootstrapBlazorLink}/blob/main/src/BootstrapBlazor.Shared/Samples/Table/CustomerFilter.razor";
/// <summary>
/// OnInitialized 方法
/// </summary>
protected override void OnInitialized()
{
base.OnInitialized();
Items = Foo.GenerateFoo(FooLocalizer);
}
private Task<QueryData<Foo>> OnQueryAsync(QueryPageOptions options)
{
IEnumerable<Foo> items = Items;
// 过滤
var isFiltered = false;
if (options.Filters.Any())
{
items = items.Where(options.Filters.GetFilterFunc<Foo>());
isFiltered = true;
}
// 排序
var isSorted = false;
// 此段代码可不写,组件内部自行处理
if (options.SortName == nameof(Foo.DateTime) && options.SortList != null)
{
var sortInvoker = Utility.GetSortListFunc<Foo>();
items = sortInvoker(items, options.SortList);
isSorted = true;
}
else if (!string.IsNullOrEmpty(options.SortName))
{
// 外部未进行排序,内部自动进行排序处理
var invoker = Utility.GetSortFunc<Foo>();
items = invoker(items, options.SortName, options.SortOrder);
isSorted = true;
}
// 设置记录总数
var total = items.Count();
// 内存分页
items = items.Skip((options.PageIndex - 1) * options.PageItems).Take(options.PageItems).ToList();
return Task.FromResult(new QueryData<Foo>()
{
Items = items,
TotalCount = total,
IsSorted = isSorted,
IsFiltered = isFiltered
});
}
}
Show filter header when the ShowFilterHeader
property value is set to true
Demo
@inject IStringLocalizer<Foo> FooLocalizer
<div>
<Table TItem="Foo"
IsPagination="true" PageItemsSource="@PageItemsSource"
IsStriped="true" IsBordered="true" IsMultipleSelect="true"
ShowSkeleton="true" ShowFilterHeader="true"
OnQueryAsync="@OnQueryAsync">
<TableColumns>
<TableColumn @bind-Field="@context.DateTime" Width="180" Sortable="true" />
<TableColumn @bind-Field="@context.Name" Width="100" Sortable="true" />
<TableColumn @bind-Field="@context.Address" Sortable="true" />
<TableColumn @bind-Field="@context.Complete" Width="100" Sortable="true" Filterable="true" />
<TableColumn @bind-Field="@context.Education" Width="100" Sortable="true" Filterable="true" />
<TableColumn @bind-Field="@context.Count" Width="100" Sortable="true" DefaultSort="true" DefaultSortOrder="@SortOrder.Desc" />
</TableColumns>
</Table>
</div>
@code {
/// <summary>
/// Foo 类为Demo测试用,如有需要请自行下载源码查阅
/// Foo class is used for Demo test, please download the source code if necessary
/// https://gitee.com/LongbowEnterprise/BootstrapBlazor/blob/main/src/BootstrapBlazor.Shared/Data/Foo.cs
/// </summary>
[NotNull]
private List<Foo>? Items { get; set; }
private static IEnumerable<int> PageItemsSource => new int[] { 4, 10, 20 };
/// <summary>
/// OnInitialized 方法
/// </summary>
protected override void OnInitialized()
{
base.OnInitialized();
Items = Foo.GenerateFoo(FooLocalizer);
}
private Task<QueryData<Foo>> OnQueryAsync(QueryPageOptions options)
{
IEnumerable<Foo> items = Items;
// 过滤
var isFiltered = false;
if (options.Filters.Any())
{
items = items.Where(options.Filters.GetFilterFunc<Foo>());
isFiltered = true;
}
// 排序
var isSorted = false;
// 此段代码可不写,组件内部自行处理
if (options.SortName == nameof(Foo.DateTime) && options.SortList != null)
{
var sortInvoker = Utility.GetSortListFunc<Foo>();
items = sortInvoker(items, options.SortList);
isSorted = true;
}
else if (!string.IsNullOrEmpty(options.SortName))
{
// 外部未进行排序,内部自动进行排序处理
var invoker = Utility.GetSortFunc<Foo>();
items = invoker(items, options.SortName, options.SortOrder);
isSorted = true;
}
// 设置记录总数
var total = items.Count();
// 内存分页
items = items.Skip((options.PageIndex - 1) * options.PageItems).Take(options.PageItems).ToList();
return Task.FromResult(new QueryData<Foo>()
{
Items = items,
TotalCount = total,
IsSorted = isSorted,
IsFiltered = isFiltered
});
}
}
Default sorts as default when setting the DefaultSort
property value to true
Demo
- Set
DefaultSort=true
to enable the default sort function, when multiple columns set this property, the first column works - Set
DefaultSortOrder
value, set default collation
In this case the default sort is the last column in reverse order
@inject IStringLocalizer<Foo> FooLocalizer
<div>
<Table TItem="Foo"
IsPagination="true" PageItemsSource="@PageItemsSource"
IsStriped="true" IsBordered="true" IsMultipleSelect="true"
ShowSkeleton="true"
OnQueryAsync="@OnQueryAsync">
<TableColumns>
<TableColumn @bind-Field="@context.DateTime" Width="180" Sortable="true" />
<TableColumn @bind-Field="@context.Name" Width="100" Sortable="true" />
<TableColumn @bind-Field="@context.Address" Sortable="true" />
<TableColumn @bind-Field="@context.Count" Width="100" Sortable="true" DefaultSort="true" DefaultSortOrder="@SortOrder.Desc" />
</TableColumns>
</Table>
</div>
@code {
/// <summary>
/// Foo 类为Demo测试用,如有需要请自行下载源码查阅
/// Foo class is used for Demo test, please download the source code if necessary
/// https://gitee.com/LongbowEnterprise/BootstrapBlazor/blob/main/src/BootstrapBlazor.Shared/Data/Foo.cs
/// </summary>
[NotNull]
private List<Foo>? Items { get; set; }
private static IEnumerable<int> PageItemsSource => new int[] { 4, 10, 20 };
/// <summary>
/// OnInitialized 方法
/// </summary>
protected override void OnInitialized()
{
base.OnInitialized();
Items = Foo.GenerateFoo(FooLocalizer);
}
private Task<QueryData<Foo>> OnQueryAsync(QueryPageOptions options)
{
IEnumerable<Foo> items = Items;
// 过滤
var isFiltered = false;
if (options.Filters.Any())
{
items = items.Where(options.Filters.GetFilterFunc<Foo>());
isFiltered = true;
}
// 排序
var isSorted = false;
// 此段代码可不写,组件内部自行处理
if (options.SortName == nameof(Foo.DateTime) && options.SortList != null)
{
var sortInvoker = Utility.GetSortListFunc<Foo>();
items = sortInvoker(items, options.SortList);
isSorted = true;
}
else if (!string.IsNullOrEmpty(options.SortName))
{
// 外部未进行排序,内部自动进行排序处理
var invoker = Utility.GetSortFunc<Foo>();
items = invoker(items, options.SortName, options.SortOrder);
isSorted = true;
}
// 设置记录总数
var total = items.Count();
// 内存分页
items = items.Skip((options.PageIndex - 1) * options.PageItems).Take(options.PageItems).ToList();
return Task.FromResult(new QueryData<Foo>()
{
Items = items,
TotalCount = total,
IsSorted = isSorted,
IsFiltered = isFiltered
});
}
}
Set the SortList
property, use this parameter for multi-column sorting when the table loads
Demo
The default collation in this case is: DeteTime desc
Address
, you don't need to handle the sort logic yourself, the component is already built-in
@inject IStringLocalizer<Foo> FooLocalizer
<div>
<Table TItem="Foo"
IsPagination="true" PageItemsSource="@PageItemsSource"
IsStriped="true" IsBordered="true" IsMultipleSelect="true"
ShowSkeleton="true" SortString="SortList"
OnQueryAsync="@OnQueryAsync">
<TableColumns>
<TableColumn @bind-Field="@context.DateTime" Width="180" Sortable="true" />
<TableColumn @bind-Field="@context.Name" Width="100" Sortable="true" />
<TableColumn @bind-Field="@context.Address" Sortable="true" />
<TableColumn @bind-Field="@context.Count" Width="100" Sortable="true" />
</TableColumns>
</Table>
</div>
@code {
/// <summary>
/// Foo 类为Demo测试用,如有需要请自行下载源码查阅
/// Foo class is used for Demo test, please download the source code if necessary
/// https://gitee.com/LongbowEnterprise/BootstrapBlazor/blob/main/src/BootstrapBlazor.Shared/Data/Foo.cs
/// </summary>
[NotNull]
private List<Foo>? Items { get; set; }
private static IEnumerable<int> PageItemsSource => new int[] { 4, 10, 20 };
/// <summary>
/// OnInitialized 方法
/// </summary>
protected override void OnInitialized()
{
base.OnInitialized();
Items = Foo.GenerateFoo(FooLocalizer);
}
private Task<QueryData<Foo>> OnQueryAsync(QueryPageOptions options)
{
IEnumerable<Foo> items = Items;
// 过滤
var isFiltered = false;
if (options.Filters.Any())
{
items = items.Where(options.Filters.GetFilterFunc<Foo>());
isFiltered = true;
}
// 排序
var isSorted = false;
// 此段代码可不写,组件内部自行处理
if (options.SortName == nameof(Foo.DateTime) && options.SortList != null)
{
var sortInvoker = Utility.GetSortListFunc<Foo>();
items = sortInvoker(items, options.SortList);
isSorted = true;
}
else if (!string.IsNullOrEmpty(options.SortName))
{
// 外部未进行排序,内部自动进行排序处理
var invoker = Utility.GetSortFunc<Foo>();
items = invoker(items, options.SortName, options.SortOrder);
isSorted = true;
}
// 设置记录总数
var total = items.Count();
// 内存分页
items = items.Skip((options.PageIndex - 1) * options.PageItems).Take(options.PageItems).ToList();
return Task.FromResult(new QueryData<Foo>()
{
Items = items,
TotalCount = total,
IsSorted = isSorted,
IsFiltered = isFiltered
});
}
}
Set OnSort
Parameters
Demo
When clicking the column header to sort, the component calls the OnSort
callback internally, where its return value can be set according to the business logic to achieve dynamic multi-column sorting, in this case, when clicking the time column header for positive order sorting, use DateTime,Count
internally, useDateTime desc, Count desc
when Count reverse order
@inject IStringLocalizer<Foo> FooLocalizer
<div>
<Table TItem="Foo"
IsPagination="true" PageItemsSource="@PageItemsSource"
IsStriped="true" IsBordered="true" IsMultipleSelect="true"
ShowSkeleton="true" SortString="@SortString" OnSort="OnSort"
OnQueryAsync="@OnQueryAsync">
<TableColumns>
<TableColumn @bind-Field="@context.DateTime" Width="180" Sortable="true" />
<TableColumn @bind-Field="@context.Name" Width="100" Sortable="true" />
<TableColumn @bind-Field="@context.Address" Sortable="true" />
<TableColumn @bind-Field="@context.Count" Width="100" Sortable="true" />
</TableColumns>
</Table>
</div>
@code {
/// <summary>
/// Foo 类为Demo测试用,如有需要请自行下载源码查阅
/// Foo class is used for Demo test, please download the source code if necessary
/// https://gitee.com/LongbowEnterprise/BootstrapBlazor/blob/main/src/BootstrapBlazor.Shared/Data/Foo.cs
/// </summary>
[NotNull]
private List<Foo>? Items { get; set; }
private static IEnumerable<int> PageItemsSource => new int[] { 4, 10, 20 };
private string SortString { get; set; } = "DateTime desc, Address";
/// <summary>
/// OnInitialized 方法
/// </summary>
protected override void OnInitialized()
{
base.OnInitialized();
Items = Foo.GenerateFoo(FooLocalizer);
}
private Task<QueryData<Foo>> OnQueryAsync(QueryPageOptions options)
{
IEnumerable<Foo> items = Items;
// 过滤
var isFiltered = false;
if (options.Filters.Any())
{
items = items.Where(options.Filters.GetFilterFunc<Foo>());
isFiltered = true;
}
// 排序
var isSorted = false;
// 此段代码可不写,组件内部自行处理
if (options.SortName == nameof(Foo.DateTime) && options.SortList != null)
{
var sortInvoker = Utility.GetSortListFunc<Foo>();
items = sortInvoker(items, options.SortList);
isSorted = true;
}
else if (!string.IsNullOrEmpty(options.SortName))
{
// 外部未进行排序,内部自动进行排序处理
var invoker = Utility.GetSortFunc<Foo>();
items = invoker(items, options.SortName, options.SortOrder);
isSorted = true;
}
// 设置记录总数
var total = items.Count();
// 内存分页
items = items.Skip((options.PageIndex - 1) * options.PageItems).Take(options.PageItems).ToList();
return Task.FromResult(new QueryData<Foo>()
{
Items = items,
TotalCount = total,
IsSorted = isSorted,
IsFiltered = isFiltered
});
}
private static string OnSort(string sortName, SortOrder sortOrder)
{
string sortString = "";
if (sortName == nameof(Foo.DateTime))
{
if (sortOrder == SortOrder.Asc)
{
sortString = "DateTime, Count";
}
else if (sortOrder == SortOrder.Desc)
{
sortString = "DateTime desc, Count desc";
}
else
{
sortString = "DateTime desc, Count";
}
}
return sortString;
}
}
Example shows how to set filters through code
Demo
@inject IStringLocalizer<TablesSetFilterInCode> Localizer
@inject IStringLocalizer<Foo> FooLocalizer
<div>
<div class="mb-2">
<Button Text="@Localizer["SetFilterInCodeButtonText1"]" OnClickWithoutRender="SetFilterInCode"></Button>
<Button Text="@Localizer["SetFilterInCodeButtonText2"]" OnClickWithoutRender="ResetAllFilters"></Button>
</div>
<Table TItem="Foo" @ref="TableSetFilter"
IsPagination="true" PageItemsSource="@PageItemsSource"
IsStriped="true" IsBordered="true" IsMultipleSelect="true"
ShowSkeleton="true" ShowFilterHeader="true"
OnQueryAsync="@OnQueryAsync">
<TableColumns>
<TableColumn @bind-Field="@context.DateTime" Width="180" Sortable="true"/>
<TableColumn @bind-Field="@context.Name" Width="100" Sortable="true" Filterable="true"/>
<TableColumn @bind-Field="@context.Address" Sortable="true"/>
<TableColumn @bind-Field="@context.Complete" Width="100" Sortable="true" Filterable="true"/>
<TableColumn @bind-Field="@context.Education" Width="100" Sortable="true" Filterable="true"/>
<TableColumn @bind-Field="@context.Count" Width="150" Sortable="true"/>
</TableColumns>
</Table>
</div>
@code {
/// <summary>
/// Foo 类为Demo测试用,如有需要请自行下载源码查阅
/// Foo class is used for Demo test, please download the source code if necessary
/// https://gitee.com/LongbowEnterprise/BootstrapBlazor/blob/main/src/BootstrapBlazor.Shared/Data/Foo.cs
/// </summary>
[NotNull]
private List<Foo>? Items { get; set; }
[NotNull]
private Table<Foo>? TableSetFilter { get; set; }
private static IEnumerable<int> PageItemsSource => new int[] { 4, 10, 20 };
/// <summary>
/// OnInitialized 方法
/// </summary>
protected override void OnInitialized()
{
base.OnInitialized();
Items = Foo.GenerateFoo(FooLocalizer);
}
private Task<QueryData<Foo>> OnQueryAsync(QueryPageOptions options)
{
IEnumerable<Foo> items = Items;
// 过滤
var isFiltered = false;
if (options.Filters.Any())
{
items = items.Where(options.Filters.GetFilterFunc<Foo>());
isFiltered = true;
}
// 排序
var isSorted = false;
// 此段代码可不写,组件内部自行处理
if (options.SortName == nameof(Foo.DateTime) && options.SortList != null)
{
var sortInvoker = Utility.GetSortListFunc<Foo>();
items = sortInvoker(items, options.SortList);
isSorted = true;
}
else if (!string.IsNullOrEmpty(options.SortName))
{
// 外部未进行排序,内部自动进行排序处理
var invoker = Utility.GetSortFunc<Foo>();
items = invoker(items, options.SortName, options.SortOrder);
isSorted = true;
}
// 设置记录总数
var total = items.Count();
// 内存分页
items = items.Skip((options.PageIndex - 1) * options.PageItems).Take(options.PageItems).ToList();
return Task.FromResult(new QueryData<Foo>()
{
Items = items,
TotalCount = total,
IsSorted = isSorted,
IsFiltered = isFiltered
});
}
private async Task SetFilterInCode()
{
//Find Column
var column = TableSetFilter.Columns.First(x => x.GetFieldName() == nameof(Foo.Name));
//Build Filter
var filters = new List<FilterKeyValueAction>()
{
new FilterKeyValueAction { FieldValue = "01", FilterAction = FilterAction.Contains }
};
//Set Filter
var filterAction = column.Filter?.FilterAction;
if (filterAction != null)
{
await filterAction.SetFilterConditionsAsync(filters);
}
}
private Task ResetAllFilters() => TableSetFilter.ResetFilters();
}
B station related video link
交流群