mirror of
https://github.com/dotnetcore/BootstrapBlazor.git
synced 2025-12-20 02:16:40 +08:00
feat(SelectTable): support Sort/Filter/Search function (#2831)
* refactor: 重构代码消除建议信息 * refactor: 更新注释 * refactor: 代码格式化 * refactor: 增加 IColumnCollection 接口 * feat: 移除 Items 改用 OnQueryAsync 回调支持排序过滤 * doc: 更新示例 * test: 增加参数异常单元测试 * test: 更新单元测试
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
<h4>下拉框为表格用于展示复杂类型的选择需求</h4>
|
||||
|
||||
<DemoBlock Title="@Localizer["NormalTitle"]" Introduction="@Localizer["NormalIntro"]" Name="Normal">
|
||||
<SelectTable TItem="Foo" @bind-Value="@_foo" Items="_items" GetTextCallback="@GetTextCallback" TableMinWidth="300">
|
||||
<SelectTable TItem="Foo" @bind-Value="@_foo" OnQueryAsync="OnQueryAsync" GetTextCallback="@GetTextCallback" TableMinWidth="300">
|
||||
<TableColumns>
|
||||
<TableColumn @bind-Field="@context.Name"></TableColumn>
|
||||
<TableColumn @bind-Field="@context.Address"></TableColumn>
|
||||
@@ -14,7 +14,7 @@
|
||||
</DemoBlock>
|
||||
|
||||
<DemoBlock Title="@Localizer["ColorTitle"]" Introduction="@Localizer["ColorIntro"]" Name="Color">
|
||||
<SelectTable TItem="Foo" @bind-Value="@_colorFoo" Items="_colorItems" GetTextCallback="@GetTextCallback" Color="Color.Info">
|
||||
<SelectTable TItem="Foo" @bind-Value="@_colorFoo" OnQueryAsync="OnQueryAsync" GetTextCallback="@GetTextCallback" Color="Color.Info">
|
||||
<TableColumns>
|
||||
<TableColumn @bind-Field="@context.Name"></TableColumn>
|
||||
<TableColumn @bind-Field="@context.Address"></TableColumn>
|
||||
@@ -23,7 +23,7 @@
|
||||
</DemoBlock>
|
||||
|
||||
<DemoBlock Title="@Localizer["IsDisabledTitle"]" Introduction="@Localizer["IsDisabledIntro"]" Name="IsDisabled">
|
||||
<SelectTable TItem="Foo" @bind-Value="@_disabledFoo" Items="_disabledItems" GetTextCallback="@GetTextCallback" IsDisabled="true">
|
||||
<SelectTable TItem="Foo" @bind-Value="@_disabledFoo" OnQueryAsync="OnQueryAsync" GetTextCallback="@GetTextCallback" IsDisabled="true">
|
||||
<TableColumns>
|
||||
<TableColumn @bind-Field="@context.Name"></TableColumn>
|
||||
<TableColumn @bind-Field="@context.Address"></TableColumn>
|
||||
@@ -32,7 +32,7 @@
|
||||
</DemoBlock>
|
||||
|
||||
<DemoBlock Title="@Localizer["TemplateTitle"]" Introduction="@Localizer["TemplateIntro"]" Name="ValueTemplate">
|
||||
<SelectTable TItem="Foo" @bind-Value="@_templateFoo" Items="_templateItems" ShowAppendArrow="false">
|
||||
<SelectTable TItem="Foo" @bind-Value="@_templateFoo" OnQueryAsync="OnQueryAsync" ShowAppendArrow="false">
|
||||
<TableColumns>
|
||||
<TableColumn @bind-Field="@context.Name"></TableColumn>
|
||||
<TableColumn @bind-Field="@context.Address"></TableColumn>
|
||||
@@ -69,7 +69,7 @@
|
||||
<ValidateForm Model="Model">
|
||||
<div class="row g-3">
|
||||
<div class="col-12">
|
||||
<SelectTable TItem="Foo" @bind-Value="@Model.Foo" Items="_validateFormItems" GetTextCallback="@GetTextCallback" DisplayText="Test">
|
||||
<SelectTable TItem="Foo" @bind-Value="@Model.Foo" OnQueryAsync="OnQueryAsync" GetTextCallback="@GetTextCallback" DisplayText="Test">
|
||||
<TableColumns>
|
||||
<TableColumn @bind-Field="@context.Name"></TableColumn>
|
||||
<TableColumn @bind-Field="@context.Address"></TableColumn>
|
||||
@@ -83,4 +83,13 @@
|
||||
</ValidateForm>
|
||||
</DemoBlock>
|
||||
|
||||
<DemoBlock Title="@Localizer["ValidateFormTitle"]" Introduction="@Localizer["ValidateFormIntro"]" Name="Sortable">
|
||||
<SelectTable TItem="Foo" @bind-Value="@Model.Foo" OnQueryAsync="OnQueryAsync" GetTextCallback="@GetTextCallback" DisplayText="Test">
|
||||
<TableColumns>
|
||||
<TableColumn @bind-Field="@context.Name" Sortable="true"></TableColumn>
|
||||
<TableColumn @bind-Field="@context.Address" Sortable="true" Filterable="true"></TableColumn>
|
||||
</TableColumns>
|
||||
</SelectTable>
|
||||
</DemoBlock>
|
||||
|
||||
<AttributeTable Items="@GetAttributes()" />
|
||||
|
||||
@@ -17,16 +17,6 @@ public partial class SelectTables
|
||||
[NotNull]
|
||||
private IStringLocalizer<SelectTables>? Localizer { get; set; }
|
||||
|
||||
private List<Foo> _items = default!;
|
||||
|
||||
private List<Foo> _colorItems = default!;
|
||||
|
||||
private List<Foo> _templateItems = default!;
|
||||
|
||||
private List<Foo> _disabledItems = default!;
|
||||
|
||||
private List<Foo> _validateFormItems = default!;
|
||||
|
||||
private Foo? _foo;
|
||||
|
||||
private Foo? _colorFoo;
|
||||
@@ -35,21 +25,54 @@ public partial class SelectTables
|
||||
|
||||
private Foo? _disabledFoo;
|
||||
|
||||
private SelectTableMode Model = new();
|
||||
private Foo? _sortableFoo;
|
||||
|
||||
private readonly SelectTableMode Model = new();
|
||||
|
||||
private static string? GetTextCallback(Foo foo) => foo.Name;
|
||||
|
||||
private List<Foo> _items = default!;
|
||||
|
||||
private IEnumerable<Foo> _filterItems = default!;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
_items = Foo.GenerateFoo(LocalizerFoo);
|
||||
_colorItems = Foo.GenerateFoo(LocalizerFoo);
|
||||
_templateItems = Foo.GenerateFoo(LocalizerFoo);
|
||||
_disabledItems = Foo.GenerateFoo(LocalizerFoo);
|
||||
_validateFormItems = Foo.GenerateFoo(LocalizerFoo);
|
||||
_filterItems = Foo.GenerateFoo(LocalizerFoo);
|
||||
}
|
||||
|
||||
private static string? GetTextCallback(Foo? foo) => foo?.Name;
|
||||
private Task<QueryData<Foo>> OnQueryAsync(QueryPageOptions options)
|
||||
{
|
||||
// 此处代码拷贝后需要自行更改根据 options 中的条件从数据库中获取数据集合
|
||||
return Task.FromResult(new QueryData<Foo>()
|
||||
{
|
||||
Items = _items
|
||||
});
|
||||
}
|
||||
|
||||
private Task<QueryData<Foo>> OnFilterQueryAsync(QueryPageOptions options)
|
||||
{
|
||||
// 此处代码拷贝后需要自行更改根据 options 中的条件从数据库中获取数据集合
|
||||
_filterItems = _filterItems.Where(options.ToFilter().GetFilterFunc<Foo>());
|
||||
|
||||
if (!string.IsNullOrEmpty(options.SortName))
|
||||
{
|
||||
_filterItems = _filterItems.Sort(options.SortName, options.SortOrder);
|
||||
}
|
||||
return Task.FromResult(new QueryData<Foo>()
|
||||
{
|
||||
Items = _filterItems.ToList(),
|
||||
IsAdvanceSearch = true,
|
||||
IsFiltered = true,
|
||||
IsSearch = true,
|
||||
IsSorted = true
|
||||
});
|
||||
}
|
||||
|
||||
class SelectTableMode
|
||||
{
|
||||
|
||||
@@ -30,7 +30,7 @@ public partial class Rate
|
||||
/// <returns></returns>
|
||||
private bool IsPartialStar(int i) => (Value + 1 - i) is > 0 and < 1;
|
||||
|
||||
private string? GetIcon(int i) => Value >= i ? StarIcon : UnStarIcon;
|
||||
private string GetIcon(int i) => Value >= i ? StarIcon : UnStarIcon;
|
||||
|
||||
private string GetWidthStyle(int i) => $"width: {Math.Round(Value + 1 - i, 2) * 100}%;";
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
</CascadingValue>
|
||||
<RenderTemplate>
|
||||
<div class="dropdown-menu dropdown-table" style="@GetStyleString">
|
||||
<Table Items="Items" TableColumns="TableColumns" IsFixedHeader="true" IsBordered="true" RenderMode="TableRenderMode.Table" ClickToSelect="true" OnClickRowCallback="OnClickRowCallback"></Table>
|
||||
<Table TableColumns="TableColumns" IsFixedHeader="true" IsBordered="true" RenderMode="TableRenderMode.Table" ClickToSelect="true" OnClickRowCallback="OnClickRowCallback" OnQueryAsync="OnQueryAsync"></Table>
|
||||
</div>
|
||||
</RenderTemplate>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace BootstrapBlazor.Components;
|
||||
/// </summary>
|
||||
/// <typeparam name="TItem"></typeparam>
|
||||
[CascadingTypeParameter(nameof(TItem))]
|
||||
public partial class SelectTable<TItem> : ITable where TItem : class, new()
|
||||
public partial class SelectTable<TItem> : IColumnCollection where TItem : class, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// 获得/设置 TableHeader 实例
|
||||
@@ -20,11 +20,12 @@ public partial class SelectTable<TItem> : ITable where TItem : class, new()
|
||||
public RenderFragment<TItem>? TableColumns { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 绑定数据集
|
||||
/// 异步查询回调方法
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[EditorRequired]
|
||||
[NotNull]
|
||||
public IEnumerable<TItem>? Items { get; set; }
|
||||
public Func<QueryPageOptions, Task<QueryData<TItem>>>? OnQueryAsync { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 颜色 默认 Color.None 无设置
|
||||
@@ -42,13 +43,14 @@ public partial class SelectTable<TItem> : ITable where TItem : class, new()
|
||||
/// 获得/设置 弹窗表格最小宽度 默认为 null 未设置使用样式中的默认值
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[NotNull]
|
||||
public int? TableMinWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得 显示文字回调方法 默认 null
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[NotNull]
|
||||
[EditorRequired]
|
||||
public Func<TItem, string?>? GetTextCallback { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -70,17 +72,6 @@ public partial class SelectTable<TItem> : ITable where TItem : class, new()
|
||||
/// </summary>
|
||||
public List<ITableColumn> Columns { get; } = [];
|
||||
|
||||
List<ITableColumn> ITable.Columns { get => Columns; }
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
Dictionary<string, IFilterAction> ITable.Filters { get; } = [];
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
Func<Task>? ITable.OnFilterAsync { get => null; }
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
IEnumerable<ITableColumn> ITable.GetVisibleColumns() => Columns;
|
||||
|
||||
/// <summary>
|
||||
/// 获得 样式集合
|
||||
/// </summary>
|
||||
@@ -124,7 +115,6 @@ public partial class SelectTable<TItem> : ITable where TItem : class, new()
|
||||
/// <summary>
|
||||
/// 获得/设置 Value 显示模板 默认 null
|
||||
/// </summary>
|
||||
/// <remarks>默认通过 <code></code></remarks>
|
||||
[Parameter]
|
||||
public RenderFragment<TItem>? Template { get; set; }
|
||||
|
||||
@@ -172,7 +162,16 @@ public partial class SelectTable<TItem> : ITable where TItem : class, new()
|
||||
{
|
||||
base.OnParametersSet();
|
||||
|
||||
Items ??= [];
|
||||
if(OnQueryAsync == null)
|
||||
{
|
||||
throw new InvalidOperationException("Please set OnQueryAsync value");
|
||||
}
|
||||
|
||||
if (GetTextCallback == null)
|
||||
{
|
||||
throw new InvalidOperationException("Please set GetTextCallback value");
|
||||
}
|
||||
|
||||
PlaceHolder ??= Localizer[nameof(PlaceHolder)];
|
||||
DropdownIcon ??= IconTheme.GetIconByKey(ComponentIcons.SelectDropdownIcon);
|
||||
}
|
||||
@@ -187,7 +186,7 @@ public partial class SelectTable<TItem> : ITable where TItem : class, new()
|
||||
/// 获得 Text 显示文字
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private string? GetText() => Value == default ? null : GetTextCallback?.Invoke(Value) ?? Value.ToString();
|
||||
private string? GetText() => Value == default ? null : GetTextCallback(Value);
|
||||
|
||||
private async Task OnClickRowCallback(TItem item)
|
||||
{
|
||||
|
||||
@@ -19,7 +19,8 @@ export function init(id) {
|
||||
EventHandler.on(popover.toggleMenu, 'click', '.tree-node', e => {
|
||||
if (popover.isPopover) {
|
||||
popover.hide()
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
const dropdown = bootstrap.Dropdown.getInstance(popover.toggleElement)
|
||||
if (dropdown) {
|
||||
dropdown.hide()
|
||||
|
||||
16
src/BootstrapBlazor/Components/Table/IColumnCollection.cs
Normal file
16
src/BootstrapBlazor/Components/Table/IColumnCollection.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
// 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/
|
||||
|
||||
namespace BootstrapBlazor.Components;
|
||||
|
||||
/// <summary>
|
||||
/// 列集合接口
|
||||
/// </summary>
|
||||
public interface IColumnCollection
|
||||
{
|
||||
/// <summary>
|
||||
/// 获得 ITableColumn 集合
|
||||
/// </summary>
|
||||
List<ITableColumn> Columns { get; }
|
||||
}
|
||||
@@ -7,13 +7,8 @@ namespace BootstrapBlazor.Components;
|
||||
/// <summary>
|
||||
/// ITable 接口
|
||||
/// </summary>
|
||||
public interface ITable
|
||||
public interface ITable : IColumnCollection
|
||||
{
|
||||
/// <summary>
|
||||
/// 获得 ITableColumn 集合
|
||||
/// </summary>
|
||||
List<ITableColumn> Columns { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得 ITable 实例配置的可见列集合
|
||||
/// </summary>
|
||||
|
||||
@@ -415,14 +415,14 @@ public class TableColumn<TItem, TType> : BootstrapComponentBase, ITableColumn
|
||||
/// 获得/设置 Table 实例
|
||||
/// </summary>
|
||||
[CascadingParameter]
|
||||
protected ITable? Table { get; set; }
|
||||
protected IColumnCollection? Columns { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 组件初始化方法
|
||||
/// </summary>
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
Table?.Columns.Add(this);
|
||||
Columns?.Columns.Add(this);
|
||||
if (FieldExpression != null)
|
||||
{
|
||||
_fieldIdentifier = FieldIdentifier.Create(FieldExpression);
|
||||
|
||||
@@ -189,7 +189,7 @@ public static class DialogServiceExtensions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 弹出保存对话窗方法
|
||||
/// 弹出带保存按钮对话窗方法
|
||||
/// </summary>
|
||||
/// <typeparam name="TComponent"></typeparam>
|
||||
/// <param name="service">DialogService 服务实例</param>
|
||||
@@ -219,7 +219,7 @@ public static class DialogServiceExtensions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 弹出保存对话窗
|
||||
/// 弹出带关闭按钮对话窗方法
|
||||
/// </summary>
|
||||
/// <typeparam name="TComponent"></typeparam>
|
||||
/// <param name="service"></param>
|
||||
|
||||
@@ -12,22 +12,39 @@ public class SelectTableTest : BootstrapBlazorTestBase
|
||||
[Fact]
|
||||
public void Items_Ok()
|
||||
{
|
||||
var localizer = Context.Services.GetRequiredService<IStringLocalizer<Foo>>();
|
||||
var items = Foo.GenerateFoo(localizer, 4);
|
||||
var cut = Context.RenderComponent<BootstrapBlazorRoot>(pb =>
|
||||
{
|
||||
pb.AddChildContent<SelectTable<Foo>>();
|
||||
pb.Add(a => a.EnableErrorLogger, false);
|
||||
pb.AddChildContent<SelectTable<Foo>>(pb =>
|
||||
{
|
||||
pb.Add(a => a.OnQueryAsync, options => OnFilterQueryAsync(options, items));
|
||||
pb.Add(a => a.GetTextCallback, foo => foo.Name);
|
||||
});
|
||||
});
|
||||
var table = cut.FindComponent<SelectTable<Foo>>();
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
table.SetParametersAndRender(pb =>
|
||||
{
|
||||
pb.Add(a => a.OnQueryAsync, null);
|
||||
});
|
||||
});
|
||||
var rows = cut.FindAll("tbody > tr");
|
||||
Assert.Empty(rows);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TableMinWidth_Ok()
|
||||
{
|
||||
var localizer = Context.Services.GetRequiredService<IStringLocalizer<Foo>>();
|
||||
var items = Foo.GenerateFoo(localizer, 4);
|
||||
var cut = Context.RenderComponent<BootstrapBlazorRoot>(pb =>
|
||||
{
|
||||
pb.AddChildContent<SelectTable<Foo>>(pb =>
|
||||
{
|
||||
pb.Add(a => a.TableMinWidth, 300);
|
||||
pb.Add(a => a.OnQueryAsync, options => OnFilterQueryAsync(options, items));
|
||||
pb.Add(a => a.GetTextCallback, foo => foo.Name);
|
||||
});
|
||||
});
|
||||
Assert.Contains("data-bb-min-width=\"300\"", cut.Markup);
|
||||
@@ -36,11 +53,15 @@ public class SelectTableTest : BootstrapBlazorTestBase
|
||||
[Fact]
|
||||
public void Color_Ok()
|
||||
{
|
||||
var localizer = Context.Services.GetRequiredService<IStringLocalizer<Foo>>();
|
||||
var items = Foo.GenerateFoo(localizer, 4);
|
||||
var cut = Context.RenderComponent<BootstrapBlazorRoot>(pb =>
|
||||
{
|
||||
pb.AddChildContent<SelectTable<Foo>>(pb =>
|
||||
{
|
||||
pb.Add(a => a.Color, Color.Danger);
|
||||
pb.Add(a => a.GetTextCallback, foo => foo.Name);
|
||||
pb.Add(a => a.OnQueryAsync, options => OnFilterQueryAsync(options, items));
|
||||
});
|
||||
});
|
||||
cut.Contains("border-danger");
|
||||
@@ -49,11 +70,15 @@ public class SelectTableTest : BootstrapBlazorTestBase
|
||||
[Fact]
|
||||
public void ShowAppendArrow_Ok()
|
||||
{
|
||||
var localizer = Context.Services.GetRequiredService<IStringLocalizer<Foo>>();
|
||||
var items = Foo.GenerateFoo(localizer, 4);
|
||||
var cut = Context.RenderComponent<BootstrapBlazorRoot>(pb =>
|
||||
{
|
||||
pb.AddChildContent<SelectTable<Foo>>(pb =>
|
||||
{
|
||||
pb.Add(a => a.ShowAppendArrow, false);
|
||||
pb.Add(a => a.OnQueryAsync, options => OnFilterQueryAsync(options, items));
|
||||
pb.Add(a => a.GetTextCallback, foo => foo.Name);
|
||||
});
|
||||
});
|
||||
cut.DoesNotContain("form-select-append");
|
||||
@@ -68,7 +93,8 @@ public class SelectTableTest : BootstrapBlazorTestBase
|
||||
{
|
||||
pb.AddChildContent<SelectTable<Foo>>(pb =>
|
||||
{
|
||||
pb.Add(a => a.Items, items);
|
||||
pb.Add(a => a.OnQueryAsync, options => OnFilterQueryAsync(options, items));
|
||||
pb.Add(a => a.GetTextCallback, foo => foo.Name);
|
||||
pb.Add(a => a.TableColumns, foo => builder =>
|
||||
{
|
||||
builder.OpenComponent<TableColumn<Foo, string>>(0);
|
||||
@@ -105,9 +131,10 @@ public class SelectTableTest : BootstrapBlazorTestBase
|
||||
var items = Foo.GenerateFoo(localizer, 4);
|
||||
var cut = Context.RenderComponent<BootstrapBlazorRoot>(pb =>
|
||||
{
|
||||
pb.Add(a => a.EnableErrorLogger, false);
|
||||
pb.AddChildContent<SelectTable<Foo>>(pb =>
|
||||
{
|
||||
pb.Add(a => a.Items, items);
|
||||
pb.Add(a => a.OnQueryAsync, options => OnFilterQueryAsync(options, items));
|
||||
pb.Add(a => a.Value, items[0]);
|
||||
pb.Add(a => a.TableColumns, foo => builder =>
|
||||
{
|
||||
@@ -131,19 +158,20 @@ public class SelectTableTest : BootstrapBlazorTestBase
|
||||
{
|
||||
pb.Add(a => a.GetTextCallback, foo => null);
|
||||
});
|
||||
Assert.Contains("value=\"BootstrapBlazor.Server.Data.Foo\"", cut.Markup);
|
||||
|
||||
table.SetParametersAndRender(pb =>
|
||||
{
|
||||
pb.Add(a => a.GetTextCallback, null);
|
||||
});
|
||||
Assert.Contains("value=\"BootstrapBlazor.Server.Data.Foo\"", cut.Markup);
|
||||
|
||||
table.SetParametersAndRender(pb =>
|
||||
{
|
||||
pb.Add(a => a.Value, null);
|
||||
});
|
||||
Assert.DoesNotContain("value=\"\"", cut.Markup);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
table.SetParametersAndRender(pb =>
|
||||
{
|
||||
pb.Add(a => a.GetTextCallback, null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -155,7 +183,7 @@ public class SelectTableTest : BootstrapBlazorTestBase
|
||||
{
|
||||
pb.AddChildContent<SelectTable<Foo>>(pb =>
|
||||
{
|
||||
pb.Add(a => a.Items, items);
|
||||
pb.Add(a => a.OnQueryAsync, options => OnFilterQueryAsync(options, items));
|
||||
pb.Add(a => a.Value, items[0]);
|
||||
pb.Add(a => a.Height, 100);
|
||||
pb.Add(a => a.TableColumns, foo => builder =>
|
||||
@@ -170,6 +198,7 @@ public class SelectTableTest : BootstrapBlazorTestBase
|
||||
builder.AddAttribute(2, "FieldExpression", Utility.GenerateValueExpression(foo, "Address", typeof(string)));
|
||||
builder.CloseComponent();
|
||||
});
|
||||
pb.Add(a => a.GetTextCallback, foo => foo.Name);
|
||||
});
|
||||
});
|
||||
Assert.Contains($"height: 100px;", cut.Markup);
|
||||
@@ -185,13 +214,14 @@ public class SelectTableTest : BootstrapBlazorTestBase
|
||||
{
|
||||
pb.AddChildContent<SelectTable<Foo>>(pb =>
|
||||
{
|
||||
pb.Add(a => a.Items, items);
|
||||
pb.Add(a => a.OnQueryAsync, options => OnFilterQueryAsync(options, items));
|
||||
pb.Add(a => a.Value, items[0]);
|
||||
pb.Add(a => a.OnValueChanged, foo =>
|
||||
{
|
||||
v = foo;
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
pb.Add(a => a.GetTextCallback, foo => foo.Name);
|
||||
pb.Add(a => a.TableColumns, foo => builder =>
|
||||
{
|
||||
builder.OpenComponent<TableColumn<Foo, string>>(0);
|
||||
@@ -245,7 +275,8 @@ public class SelectTableTest : BootstrapBlazorTestBase
|
||||
model.Foo = v;
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
pb.Add(a => a.Items, items);
|
||||
pb.Add(a => a.GetTextCallback, foo => foo.Name);
|
||||
pb.Add(a => a.OnQueryAsync, options => OnFilterQueryAsync(options, items));
|
||||
pb.Add(a => a.TableColumns, foo => builder =>
|
||||
{
|
||||
builder.OpenComponent<TableColumn<Foo, string>>(0);
|
||||
@@ -279,6 +310,24 @@ public class SelectTableTest : BootstrapBlazorTestBase
|
||||
Assert.True(invalid);
|
||||
}
|
||||
|
||||
private Task<QueryData<Foo>> OnFilterQueryAsync(QueryPageOptions options, IEnumerable<Foo> _filterItems)
|
||||
{
|
||||
_filterItems = _filterItems.Where(options.ToFilter().GetFilterFunc<Foo>());
|
||||
|
||||
if (!string.IsNullOrEmpty(options.SortName))
|
||||
{
|
||||
_filterItems = _filterItems.Sort(options.SortName, options.SortOrder);
|
||||
}
|
||||
return Task.FromResult(new QueryData<Foo>()
|
||||
{
|
||||
Items = _filterItems.ToList(),
|
||||
IsAdvanceSearch = true,
|
||||
IsFiltered = true,
|
||||
IsSearch = true,
|
||||
IsSorted = true
|
||||
});
|
||||
}
|
||||
|
||||
class SelectTableModel()
|
||||
{
|
||||
public Foo? Foo { get; set; }
|
||||
|
||||
Reference in New Issue
Block a user