
筛选和排序功能
筛选可快速查找到自己想看的数据;排序可快速查找或对比数据。
- 对某一列数据进行筛选,通过指定列的
Filterable
属性来指定需要筛选的列 - 对某一列数据进行排序,通过指定列的
Sortable
属性来指定需要排序的列,通过多次点击更改排序规则
可筛选数据的表格
设置 TableColumn
列的 Filterable
属性,控制列头是否开启数据筛选功能
Demo
Filterable
目前支持两种应用方式:
- 查询方法参数中的
Filters
是筛选条件,数据库查询数据时可以通过此属性自行进行数据筛选 - 无感使用,正常查询数据,对筛选不进行任何处理,组件内部将根据
Filter
进行内部处理 - 外部已经进行了筛选时请设置
QueryData<TItem>
参数的IsFiltered
属性值为true
- 各列可分别设置筛选条件,各列之间筛选条件为
And
并且的关系
本示例分别为
DateTime、string、bool、enum、int
类型,弹出筛选框也分别不同
自定义筛选模板
设置 FilterTemplate
模板值,自定义列筛选模板,非常适用于复杂类型的筛选弹窗
Demo
FilterTemplate
类型为 RenderFragment
:
其值为自定义组件,组件必须继承 FilterBase
本例中最后一列 数量列 通过筛选模板使用自定义组件 CustomerFilter
[传送门] CustomerFilter 组件源码
默认排序功能
设置 DefaultSort
属性值为 true
时作为默认排序列
Demo
- 设置
DefaultSort=true
开启默认排序功能,当多列设置此属性时,第一列起作用 - 设置
DefaultSortOrder
值,设置默认排序规则
本例中默认排序为最后一列倒序排序
@inherits TablesBaseQuery
@page "/tables/filter"
<h3>筛选和排序功能</h3>
<h4>筛选可快速查找到自己想看的数据;排序可快速查找或对比数据。</h4>
<ul class="ul-demo mt-3">
<li>对某一列数据进行筛选,通过指定列的 <code>Filterable</code> 属性来指定需要筛选的列</li>
<li>对某一列数据进行排序,通过指定列的 <code>Sortable</code> 属性来指定需要排序的列,通过多次点击更改排序规则</li>
</ul>
<Block Title="可筛选数据的表格" Introduction="设置 <code>TableColumn</code> 列的 <code>Filterable</code> 属性,控制列头是否开启数据筛选功能">
<p>
<code>Filterable</code> 目前支持两种应用方式:
</p>
<ul class="ul-demo">
<li>查询方法参数中的 <code>Filters</code> 是筛选条件,数据库查询数据时可以通过此属性自行进行数据筛选</li>
<li>无感使用,正常查询数据,对筛选不进行任何处理,组件内部将根据 <code>Filter</code> 进行内部处理</li>
<li>外部已经进行了筛选时请设置 <code>QueryData<TItem></code> 参数的 <code>IsFiltered</code> 属性值为 <code>true</code></li>
<li>各列可分别设置筛选条件,各列之间筛选条件为 <code>And</code> 并且的关系</li>
</ul>
<div>
本示例分别为 <code>DateTime、string、bool、enum、int</code> 类型,弹出筛选框也分别不同
</div>
<Alert ShowBar="true" Color="Color.Info" class="mt-3">开启筛选功能仅需要设置 <code>TableColumn</code> 的 <code>Filterable</code> 值为 <code>true</code>,无需额外任何代码</Alert>
<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.Education" Width="100" Sortable="true" Filterable="true">
<Template Context="value">
<span>@value.Value?.ToDescriptionString()</span>
</Template>
</TableColumn>
<TableColumn @bind-Field="@context.Count" Width="100" Sortable="true" Filterable="true" />
</TableColumns>
</Table>
</Block>
<Block Title="自定义筛选模板" Introduction="设置 <code>FilterTemplate</code> 模板值,自定义列筛选模板,非常适用于复杂类型的筛选弹窗">
<p>
<code>FilterTemplate</code> 类型为 <code>RenderFragment</code>:
<span>其值为自定义组件,组件必须继承</span> <code>FilterBase</code> 本例中最后一列 <b>数量列</b> 通过筛选模板使用自定义组件 <code>CustomerFilter</code>
<a href="https://gitee.com/LongbowEnterprise/BootstrapBlazor/blob/dev/src/BootstrapBlazor.Shared/Pages/Table/CustomerFilter.razor" target="_blank">[传送门] CustomerFilter 组件源码</a>
</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>
</Block>
<Block Title="默认排序功能" Introduction="设置 <code>DefaultSort</code> 属性值为 <code>true</code> 时作为默认排序列">
<ul class="ul-demo">
<li>设置 <code>DefaultSort=true</code> 开启默认排序功能,当多列设置此属性时,第一列起作用</li>
<li>设置 <code>DefaultSortOrder</code> 值,设置默认排序规则</li>
</ul>
<p>本例中默认排序为最后一列倒序排序</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" />
<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>
</Block>
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/
using BootstrapBlazor.Components;
using BootstrapBlazor.Shared.Pages.Components;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BootstrapBlazor.Shared.Pages
{
/// <summary>
///
/// </summary>
public abstract class TablesBaseQuery : TablesBase
{
private static readonly ConcurrentDictionary<Type, Func<IEnumerable<Foo>, string, SortOrder, IEnumerable<Foo>>> SortLambdaCache = new();
/// <summary>
///
/// </summary>
protected Foo SearchModel { get; set; } = new Foo();
/// <summary>
///
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
protected static Task OnResetSearchAsync(Foo item)
{
item.Name = "";
item.Address = "";
return Task.CompletedTask;
}
/// <summary>
///
/// </summary>
protected static IEnumerable<int> PageItemsSource => new int[] { 2, 4, 10, 20 };
/// <summary>
///
/// </summary>
/// <param name="options"></param>
/// <returns></returns>
protected Task<QueryData<Foo>> OnQueryAsync(QueryPageOptions options) => FooQueryAsync(Items, options);
/// <summary>
///
/// </summary>
/// <param name="items"></param>
/// <param name="options"></param>
/// <returns></returns>
protected Task<QueryData<Foo>> FooQueryAsync(IEnumerable<Foo> items, QueryPageOptions options)
{
if (!string.IsNullOrEmpty(SearchModel.Name)) items = items.Where(item => item.Name?.Contains(SearchModel.Name, StringComparison.OrdinalIgnoreCase) ?? false);
if (!string.IsNullOrEmpty(SearchModel.Address)) items = items.Where(item => item.Address?.Contains(SearchModel.Address, StringComparison.OrdinalIgnoreCase) ?? false);
if (options.Searchs.Any())
{
// 针对 SearchText 进行模糊查询
items = items.Where(options.Searchs.GetFilterFunc<Foo>(FilterLogic.Or));
}
else
{
if (!string.IsNullOrEmpty(options.SearchText))
items = items.Where(item => (item.Name?.Contains(options.SearchText) ?? false)
|| (item.Address?.Contains(options.SearchText) ?? false));
}
// 过滤
var isFiltered = false;
if (options.Filters.Any())
{
items = items.Where(options.Filters.GetFilterFunc<Foo>());
isFiltered = true;
}
// 排序
var isSorted = false;
if (!string.IsNullOrEmpty(options.SortName))
{
// 外部未进行排序,内部自动进行排序处理
var invoker = SortLambdaCache.GetOrAdd(typeof(Foo), key => LambdaExtensions.GetSortLambda<Foo>().Compile());
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,
IsSearch = !string.IsNullOrEmpty(SearchModel.Name) || !string.IsNullOrEmpty(SearchModel.Address)
});
}
}
}