Skip to content

Commit

Permalink
feat(Table): render tooltip support LookupService GetItemByKeyAsync (#…
Browse files Browse the repository at this point in the history
…4926)

* refactor: 复用 IsLookup 扩展方法

Co-Authored-By: ZhYan <19183404+Axxbis@users.noreply.github.com>

* refactor: 表格支持 Lookup 异步获取数据

* refactor: Tooltip 支持异步 Lookup

* refactor: 增加 Lookup 异步支持

Co-Authored-By: ZhYan <19183404+Axxbis@users.noreply.github.com>

* test: 更新单元测试

Co-Authored-By: ZhYan <19183404+Axxbis@users.noreply.github.com>

* refactor: 代码重构

---------

Co-Authored-By: ZhYan <19183404+Axxbis@users.noreply.github.com>
  • Loading branch information
ArgoZhang and Axxbis authored Dec 23, 2024
1 parent 8de9a2e commit 29bb8a0
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 21 deletions.
2 changes: 1 addition & 1 deletion src/BootstrapBlazor/Components/Filters/TableFilter.razor
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ else
{
<EnumFilter Type="Column.PropertyType" Count="_count"></EnumFilter>
}
else if (IsLookup)
else if (Column.IsLookup())
{
<LookupFilter Lookup="Column.Lookup" LookupService="Column.LookupService" LookupServiceKey="Column.LookupServiceKey" LookupServiceData="Column.LookupServiceData" LookupStringComparison="Column.LookupStringComparison" Type="Column.PropertyType" IsShowSearch="Column.ShowSearchWhenSelect"></LookupFilter>
}
Expand Down
2 changes: 0 additions & 2 deletions src/BootstrapBlazor/Components/Filters/TableFilter.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,4 @@ private void OnClickMinus()
_count--;
}
}

private bool IsLookup => Column.Lookup != null || !string.IsNullOrEmpty(Column.LookupServiceKey);
}
8 changes: 1 addition & 7 deletions src/BootstrapBlazor/Components/Table/Table.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1296,13 +1296,7 @@ protected RenderFragment GetValue(ITableColumn col, TItem item) => builder =>
}
else
{
if (col.Lookup == null && !string.IsNullOrEmpty(col.LookupServiceKey))
{
// 未设置 Lookup
// 设置 LookupService 键值
col.Lookup = LookupService.GetItemsByKey(col.LookupServiceKey, col.LookupServiceData);
}
builder.AddContent(20, col.RenderValue(item));
builder.AddContent(20, col.RenderValue(item, LookupService));
}
};
#endregion
Expand Down
2 changes: 1 addition & 1 deletion src/BootstrapBlazor/Extensions/IEditorItemExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static class IEditorItemExtensions
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public static bool IsLookup(this IEditorItem item) => item.Lookup != null || item.LookupService != null || !string.IsNullOrEmpty(item.LookupServiceKey);
public static bool IsLookup(this IEditorItem item) => item.Lookup != null || !string.IsNullOrEmpty(item.LookupServiceKey);

/// <summary>
/// 判断当前 IEditorItem 实例是否可以编辑
Expand Down
31 changes: 21 additions & 10 deletions src/BootstrapBlazor/Extensions/ITableColumnExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,17 +172,20 @@ public static List<IFilterAction> ToSearches(this IEnumerable<ITableColumn> colu
return searches;
}

internal static RenderFragment RenderValue<TItem>(this ITableColumn col, TItem item) => builder =>
/// <summary>
/// 当前单元格方法
/// </summary>
/// <typeparam name="TItem"></typeparam>
/// <param name="col"></param>
/// <param name="item"></param>
/// <param name="lookupService"></param>
/// <returns></returns>
public static RenderFragment RenderValue<TItem>(this ITableColumn col, TItem item, ILookupService lookupService) => builder =>
{
var val = col.GetItemValue(item);
if (col.Lookup != null && val != null)
if (col.IsLookup() && val != null)
{
// 转化 Lookup 数据源
var lookupVal = col.Lookup.FirstOrDefault(l => l.Value.Equals(val.ToString(), col.LookupStringComparison));
if (lookupVal != null)
{
builder.AddContent(10, col.RenderTooltip(lookupVal.Text, item));
}
builder.AddContent(10, col.RenderTooltip(val.ToString(), item, lookupService));
}
else if (val is bool v1)
{
Expand Down Expand Up @@ -218,7 +221,7 @@ internal static RenderFragment RenderValue<TItem>(this ITableColumn col, TItem i
{
content = val?.ToString();
}
builder.AddContent(30, col.RenderTooltip(content, item));
builder.AddContent(30, col.RenderTooltip(content, item, lookupService));
}
}
};
Expand All @@ -243,7 +246,7 @@ internal static RenderFragment RenderColor<TItem>(this ITableColumn col, TItem i
builder.CloseElement();
};

private static RenderFragment RenderTooltip<TItem>(this ITableColumn col, string? text, TItem item) => pb =>
private static RenderFragment RenderTooltip<TItem>(this ITableColumn col, string? text, TItem item, ILookupService lookupService) => pb =>
{
if (col.GetShowTips())
{
Expand All @@ -254,6 +257,14 @@ private static RenderFragment RenderTooltip<TItem>(this ITableColumn col, string
{
pb.AddAttribute(10, nameof(Tooltip.GetTitleCallback), new Func<Task<string?>>(() => col.GetTooltipTextCallback(item)));
}
else if (col.IsLookup())
{
pb.AddAttribute(10, nameof(Tooltip.GetTitleCallback), new Func<Task<string?>>(async () =>
{
var lookup = col.Lookup ?? await col.GetLookupService(lookupService).GetItemsAsync(col.LookupServiceKey, col.LookupServiceData);
return lookup?.FirstOrDefault(l => string.Equals(l.Value, text, col.LookupStringComparison))?.Text ?? text;
}));
}
else
{
pb.AddAttribute(11, nameof(Tooltip.Title), tooltipText);
Expand Down
100 changes: 100 additions & 0 deletions test/UnitTest/Components/TableTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7665,6 +7665,106 @@ public async Task GetValue_LookupServiceKey()

var table = cut.FindComponent<MockTable>();
await cut.InvokeAsync(() => table.Instance.QueryAsync());

col.SetParametersAndRender(pb =>
{
pb.Add(a => a.ShowTips, true);
pb.Add(a => a.Lookup, null);
pb.Add(a => a.LookupService, new MockLookupServiceAsync());
});
await cut.InvokeAsync(() => table.Instance.QueryAsync());
cut.WaitForElement("[data-bs-original-title=\"LookupService-Test-True-async\"]");
}

[Fact]
public async Task GetValue_LookupServiceKey_Null()
{
var localizer = Context.Services.GetRequiredService<IStringLocalizer<Foo>>();
var cut = Context.RenderComponent<BootstrapBlazorRoot>(pb =>
{
pb.AddChildContent<MockTable>(pb =>
{
pb.Add(a => a.OnQueryAsync, OnQueryAsync(localizer));
pb.Add(a => a.TableColumns, foo => builder =>
{
builder.OpenComponent<TableColumn<Foo, bool>>(0);
builder.AddAttribute(1, "Field", true);
builder.AddAttribute(2, "FieldExpression", Utility.GenerateValueExpression(foo, "Complete", typeof(bool)));
builder.AddAttribute(3, "LookupServiceKey", "null");
builder.AddAttribute(4, "LookupServiceData", true);
builder.AddAttribute(5, "ShowTips", true);
builder.AddAttribute(6, "LookupService", new MockLookupServiceAsync());
builder.CloseComponent();
});
});
});

var table = cut.FindComponent<MockTable>();
await cut.InvokeAsync(() => table.Instance.QueryAsync());
cut.WaitForElement("[data-bs-original-title=\"True\"]");
}

[Fact]
public async Task GetValue_LookupServiceKey_NullText()
{
var localizer = Context.Services.GetRequiredService<IStringLocalizer<Foo>>();
var cut = Context.RenderComponent<BootstrapBlazorRoot>(pb =>
{
pb.AddChildContent<MockTable>(pb =>
{
pb.Add(a => a.OnQueryAsync, OnQueryAsync(localizer));
pb.Add(a => a.TableColumns, foo => builder =>
{
builder.OpenComponent<TableColumn<Foo, bool>>(0);
builder.AddAttribute(1, "Field", true);
builder.AddAttribute(2, "FieldExpression", Utility.GenerateValueExpression(foo, "Complete", typeof(bool)));
builder.AddAttribute(3, "LookupServiceKey", "null-text");
builder.AddAttribute(4, "LookupServiceData", true);
builder.AddAttribute(5, "ShowTips", true);
builder.AddAttribute(6, "LookupService", new MockLookupServiceAsync());
builder.CloseComponent();
});
});
});

var table = cut.FindComponent<MockTable>();
await cut.InvokeAsync(() => table.Instance.QueryAsync());
cut.WaitForElement("[data-bs-original-title=\"True\"]");
}
class MockLookupServiceAsync : LookupServiceBase
{
public override IEnumerable<SelectedItem>? GetItemsByKey(string? key, object? data) => null;

public override async Task<IEnumerable<SelectedItem>?> GetItemsByKeyAsync(string? key, object? data)
{
await Task.Delay(300);

IEnumerable<SelectedItem>? ret = null;

if (key == "test")
{
ret = new SelectedItem[]
{
new("True", "LookupService-Test-True-async"),
new("False", "LookupService-Test-False-async")
};
}

if (key == "null")
{
ret = null;
}

if (key == "null-text")
{
ret = new SelectedItem[]
{
new("Fake-True", "Fake-True"),
new("Fake-False", "Fake-False")
};
}
return ret;
}
}

[Fact]
Expand Down

0 comments on commit 29bb8a0

Please sign in to comment.