Skip to content

Commit dc943bb

Browse files
authored
feat(ILookupService): add GetItemsByKeyAsync method (#4816)
* refactor: 增加 GetItemsByKeyAsync 方法 * refactor: 增加 GetItemsAsync 扩展方法 * refactor: 改造 Lookup 使用方法支持异步方法 * refactor: IEditorItem 增加 LookupService 属性 * refactor: 改造 EditorForm 支持异步字典 * refactor: 改造 LookupFilter 支持异步 Lookup * test: 跟新 EditorForm 单元测试支持异步 Lookup * test: 更新单元测试支持异步 Lookup * test: 更新单元测试 * test: 更新单元测试 * test: 更新单元测试 * test: 更新单元测试 * test: 更新 EditorForm 单元测试 * test: 更新单元测试 * test: 增加单元测试 * chore: bump version 9.1.3-beta02
1 parent a85cd0c commit dc943bb

27 files changed

+358
-103
lines changed

src/BootstrapBlazor/Attributes/AutoGenerateColumnAttribute.cs

+5
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,11 @@ public class AutoGenerateColumnAttribute : AutoGenerateBaseAttribute, ITableColu
327327
/// </summary>
328328
public object? LookupServiceData { get; set; }
329329

330+
/// <summary>
331+
/// <inheritdoc/>
332+
/// </summary>
333+
ILookupService? IEditorItem.LookupService { get; set; }
334+
330335
/// <summary>
331336
/// 获得/设置 单元格回调方法
332337
/// </summary>

src/BootstrapBlazor/BootstrapBlazor.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk.Razor">
22

33
<PropertyGroup>
4-
<Version>9.1.3-beta01</Version>
4+
<Version>9.1.3-beta02</Version>
55
</PropertyGroup>
66

77
<ItemGroup>

src/BootstrapBlazor/Components/EditorForm/EditorForm.razor

+1-4
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@
77
@FieldItems?.Invoke(Model)
88
</CascadingValue>
99
<CascadingValue Value="this" Name="EditorForm">
10-
<RenderTemplate OnRenderAsync="OnRenderAsync">
11-
@{
12-
ResetItems();
13-
}
10+
<RenderTemplate>
1411
@if (ShowUnsetGroupItemsOnTop)
1512
{
1613
if (UnsetGroupItems.Any())

src/BootstrapBlazor/Components/EditorForm/EditorForm.razor.cs

+63-49
Original file line numberDiff line numberDiff line change
@@ -184,19 +184,25 @@ public partial class EditorForm<TModel> : IShowLabel
184184
/// </summary>
185185
private readonly List<IEditorItem> _editorItems = [];
186186

187-
/// <summary>
188-
/// 获得/设置 渲染的编辑项集合
189-
/// </summary>
190-
[NotNull]
191-
private List<IEditorItem>? _formItems = null;
187+
private IEnumerable<IEditorItem> UnsetGroupItems => RenderItems.Where(i => string.IsNullOrEmpty(i.GroupName) && i.IsVisible(ItemChangedType, IsSearch.Value));
192188

193-
private IEnumerable<IEditorItem> UnsetGroupItems => _formItems.Where(i => string.IsNullOrEmpty(i.GroupName) && i.IsVisible(ItemChangedType, IsSearch.Value));
194-
195-
private IEnumerable<KeyValuePair<string, IOrderedEnumerable<IEditorItem>>> GroupItems => _formItems
189+
private IEnumerable<KeyValuePair<string, IOrderedEnumerable<IEditorItem>>> GroupItems => RenderItems
196190
.Where(i => !string.IsNullOrEmpty(i.GroupName) && i.IsVisible(ItemChangedType, IsSearch.Value))
197191
.GroupBy(i => i.GroupOrder).OrderBy(i => i.Key)
198192
.Select(i => new KeyValuePair<string, IOrderedEnumerable<IEditorItem>>(i.First().GroupName!, i.OrderBy(x => x.Order)));
199193

194+
private bool _inited;
195+
private List<IEditorItem>? _itemsCache;
196+
197+
private List<IEditorItem> RenderItems
198+
{
199+
get
200+
{
201+
_itemsCache ??= GetRenderItems();
202+
return _itemsCache;
203+
}
204+
}
205+
200206
/// <summary>
201207
/// OnInitialized 方法
202208
/// </summary>
@@ -217,7 +223,6 @@ protected override void OnInitialized()
217223

218224
// 统一设置所有 IEditorItem 的 PlaceHolder
219225
PlaceHolderText ??= Localizer[nameof(PlaceHolderText)];
220-
221226
IsSearch ??= false;
222227
}
223228

@@ -230,66 +235,75 @@ protected override void OnParametersSet()
230235

231236
// 为空时使用级联参数 ValidateForm 的 ShowLabel
232237
ShowLabel ??= ValidateForm?.ShowLabel;
233-
_formItems = null;
238+
_itemsCache = null;
234239
}
235240

236-
private bool _inited;
237-
238-
private Task OnRenderAsync(bool firstRender)
241+
/// <summary>
242+
/// <inheritdoc/>
243+
/// </summary>
244+
/// <param name="firstRender"></param>
245+
protected override async Task OnAfterRenderAsync(bool firstRender)
239246
{
247+
await base.OnAfterRenderAsync(firstRender);
248+
240249
if (firstRender)
241250
{
251+
foreach (var item in RenderItems)
252+
{
253+
if (item.Lookup == null && !string.IsNullOrEmpty(item.LookupServiceKey))
254+
{
255+
var lookupServcie = item.LookupService ?? LookupService;
256+
item.Lookup = await lookupServcie.GetItemsAsync(item.LookupServiceKey, item.LookupServiceData);
257+
}
258+
}
242259
_inited = true;
243260
StateHasChanged();
244261
}
245-
return Task.CompletedTask;
246262
}
247263

248-
private void ResetItems()
264+
private List<IEditorItem> GetRenderItems()
249265
{
250-
if (_formItems == null)
266+
var items = new List<IEditorItem>();
267+
if (Items != null)
251268
{
252-
_formItems = [];
253-
if (Items != null)
254-
{
255-
_formItems.AddRange(Items.Where(i => !i.GetIgnore() && !string.IsNullOrEmpty(i.GetFieldName())));
256-
}
257-
else
269+
items.AddRange(Items.Where(i => !i.GetIgnore() && !string.IsNullOrEmpty(i.GetFieldName())));
270+
}
271+
else
272+
{
273+
// 如果 EditorItems 有值表示 用户自定义列
274+
if (AutoGenerateAllItem)
258275
{
259-
// 如果 EditorItems 有值表示 用户自定义列
260-
if (AutoGenerateAllItem)
261-
{
262-
// 获取绑定模型所有属性
263-
var items = Utility.GetTableColumns<TModel>(defaultOrderCallback: ColumnOrderCallback).ToList();
276+
// 获取绑定模型所有属性
277+
var columns = Utility.GetTableColumns<TModel>(defaultOrderCallback: ColumnOrderCallback).ToList();
264278

265-
// 通过设定的 FieldItems 模板获取项进行渲染
266-
foreach (var el in _editorItems)
279+
// 通过设定的 FieldItems 模板获取项进行渲染
280+
foreach (var el in _editorItems)
281+
{
282+
var item = columns.FirstOrDefault(i => i.GetFieldName() == el.GetFieldName());
283+
if (item != null)
267284
{
268-
var item = items.FirstOrDefault(i => i.GetFieldName() == el.GetFieldName());
269-
if (item != null)
285+
// 过滤掉不编辑与不可见的列
286+
if (el.GetIgnore() || !el.IsVisible(ItemChangedType, IsSearch.Value) || string.IsNullOrEmpty(el.GetFieldName()))
270287
{
271-
// 过滤掉不编辑与不可见的列
272-
if (el.GetIgnore() || !el.IsVisible(ItemChangedType, IsSearch.Value))
273-
{
274-
items.Remove(item);
275-
}
276-
else
277-
{
278-
// 设置只读属性与列模板
279-
item.CopyValue(el);
280-
}
288+
columns.Remove(item);
289+
}
290+
else
291+
{
292+
// 设置只读属性与列模板
293+
item.CopyValue(el);
281294
}
282295
}
283-
_formItems.AddRange(items.Where(i => !string.IsNullOrEmpty(i.GetFieldName())));
284-
}
285-
else
286-
{
287-
_formItems.AddRange(_editorItems.Where(i => !i.GetIgnore()
288-
&& !string.IsNullOrEmpty(i.GetFieldName())
289-
&& i.IsVisible(ItemChangedType, IsSearch.Value)));
290296
}
297+
items.AddRange(columns);
298+
}
299+
else
300+
{
301+
items.AddRange(_editorItems.Where(i => !i.GetIgnore()
302+
&& !string.IsNullOrEmpty(i.GetFieldName())
303+
&& i.IsVisible(ItemChangedType, IsSearch.Value)));
291304
}
292305
}
306+
return items;
293307
}
294308

295309
private RenderFragment AutoGenerateTemplate(IEditorItem item) => builder =>
@@ -301,7 +315,7 @@ private RenderFragment AutoGenerateTemplate(IEditorItem item) => builder =>
301315
else
302316
{
303317
item.PlaceHolder ??= PlaceHolderText;
304-
builder.CreateComponentByFieldType(this, item, Model, ItemChangedType, IsSearch.Value, LookupService);
318+
builder.CreateComponentByFieldType(this, item, Model, ItemChangedType, IsSearch.Value);
305319
}
306320
};
307321

src/BootstrapBlazor/Components/EditorForm/EditorItem.cs

+6
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,12 @@ public class EditorItem<TValue> : ComponentBase, IEditorItem
194194
[Parameter]
195195
public object? LookupServiceData { get; set; }
196196

197+
/// <summary>
198+
/// <inheritdoc/>
199+
/// </summary>
200+
[Parameter]
201+
public ILookupService? LookupService { get; set; }
202+
197203
/// <summary>
198204
/// 获得/设置 自定义验证集合
199205
/// </summary>

src/BootstrapBlazor/Components/EditorForm/IEditorItem.cs

+5
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ public interface IEditorItem
111111
/// </summary>
112112
object? LookupServiceData { get; set; }
113113

114+
/// <summary>
115+
/// 获得/设置 <see cref="ILookupService"/> 服务实例
116+
/// </summary>
117+
ILookupService? LookupService { get; set; }
118+
114119
/// <summary>
115120
/// 获得/设置 自定义验证集合
116121
/// </summary>
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
@namespace BootstrapBlazor.Components
22
@inherits FilterBase
33

4-
@if (IsHeaderRow)
4+
@if(Items != null)
55
{
6-
<Select Items="@Items" StringComparison="LookupStringComparison" @bind-Value="@Value" OnSelectedItemChanged="_ => OnFilterValueChanged()" IsPopover="true" ShowSearch="IsShowSearch"></Select>
7-
}
8-
else
9-
{
10-
<Select Items="@Items" StringComparison="LookupStringComparison" @bind-Value="@Value" ShowSearch="IsShowSearch" ></Select>
6+
if (IsHeaderRow)
7+
{
8+
<Select Items="@Items" StringComparison="LookupStringComparison" @bind-Value="@Value" OnSelectedItemChanged="_ => OnFilterValueChanged()" IsPopover="true" ShowSearch="IsShowSearch"></Select>
9+
}
10+
else
11+
{
12+
<Select Items="@Items" StringComparison="LookupStringComparison" @bind-Value="@Value" ShowSearch="IsShowSearch" ></Select>
13+
}
1114
}

src/BootstrapBlazor/Components/Filters/LookupFilter.razor.cs

+40-16
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,31 @@ public partial class LookupFilter
1717
/// <summary>
1818
/// 获得/设置 相关枚举类型
1919
/// </summary>
20-
#if NET6_0_OR_GREATER
21-
[EditorRequired]
22-
#endif
2320
[Parameter]
2421
[NotNull]
2522
public IEnumerable<SelectedItem>? Lookup { get; set; }
2623

24+
/// <summary>
25+
/// 获得/设置 <see cref="ILookupService"/> 服务实例
26+
/// </summary>
27+
[Parameter]
28+
[NotNull]
29+
public ILookupService? LookupService { get; set; }
30+
31+
/// <summary>
32+
/// 获得/设置 <see cref="ILookupService"/> 服务获取 Lookup 数据集合键值 常用于外键自动转换为名称操作,可以通过 <see cref="LookupServiceData"/> 传递自定义数据
33+
/// </summary>
34+
[Parameter]
35+
[NotNull]
36+
public string? LookupServiceKey { get; set; }
37+
38+
/// <summary>
39+
/// 获得/设置 <see cref="ILookupService"/> 服务获取 Lookup 数据集合键值自定义数据,通过 <see cref="LookupServiceKey"/> 指定键值
40+
/// </summary>
41+
[Parameter]
42+
[NotNull]
43+
public object? LookupServiceData { get; set; }
44+
2745
/// <summary>
2846
/// 获得/设置 字典数据源字符串比较规则 默认 StringComparison.OrdinalIgnoreCase 大小写不敏感
2947
/// </summary>
@@ -33,9 +51,7 @@ public partial class LookupFilter
3351
/// <summary>
3452
/// 获得/设置 相关枚举类型
3553
/// </summary>
36-
#if NET6_0_OR_GREATER
3754
[EditorRequired]
38-
#endif
3955
[Parameter]
4056
[NotNull]
4157
public Type? Type { get; set; }
@@ -50,18 +66,17 @@ public partial class LookupFilter
5066
[NotNull]
5167
private IStringLocalizer<TableFilter>? Localizer { get; set; }
5268

69+
[Inject]
70+
[NotNull]
71+
private ILookupService? InjectLookupService { get; set; }
72+
5373
/// <summary>
5474
/// <inheritdoc/>
5575
/// </summary>
5676
protected override void OnInitialized()
5777
{
5878
base.OnInitialized();
5979

60-
if (Lookup == null)
61-
{
62-
throw new InvalidOperationException("the Parameter Lookup must be set.");
63-
}
64-
6580
if (Type == null)
6681
{
6782
throw new InvalidOperationException("the Parameter Type must be set.");
@@ -76,19 +91,28 @@ protected override void OnInitialized()
7691
/// <summary>
7792
/// <inheritdoc/>
7893
/// </summary>
79-
protected override void OnParametersSet()
94+
protected override async Task OnParametersSetAsync()
8095
{
81-
base.OnParametersSet();
96+
await base.OnParametersSetAsync();
8297

83-
if (Items == null)
84-
{
85-
var items = new List<SelectedItem>
98+
var items = new List<SelectedItem>
8699
{
87100
new("", Localizer["EnumFilter.AllText"].Value)
88101
};
102+
if (Lookup != null)
103+
{
89104
items.AddRange(Lookup);
90-
Items = items;
91105
}
106+
else if (!string.IsNullOrEmpty(LookupServiceKey))
107+
{
108+
var lookupService = LookupService ?? InjectLookupService;
109+
var lookup = await lookupService.GetItemsAsync(LookupServiceKey, LookupServiceData);
110+
if (lookup != null)
111+
{
112+
items.AddRange(lookup);
113+
}
114+
}
115+
Items = items;
92116
}
93117

94118
/// <summary>

src/BootstrapBlazor/Components/Filters/TableFilter.razor

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ else
4646
}
4747
else if (IsLookup)
4848
{
49-
<LookupFilter Lookup="_lookup.Value" LookupStringComparison="Column.LookupStringComparison" Type="Column.PropertyType" IsShowSearch="Column.ShowSearchWhenSelect"></LookupFilter>
49+
<LookupFilter Lookup="Column.Lookup" LookupService="Column.LookupService" LookupServiceKey="Column.LookupServiceKey" LookupServiceData="Column.LookupServiceData" LookupStringComparison="Column.LookupStringComparison" Type="Column.PropertyType" IsShowSearch="Column.ShowSearchWhenSelect"></LookupFilter>
5050
}
5151
else
5252
{

src/BootstrapBlazor/Components/Filters/TableFilter.razor.cs

-13
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,7 @@ public partial class TableFilter : IFilter
9393
/// </summary>
9494
[Parameter]
9595
[NotNull]
96-
#if NET6_0_OR_GREATER
9796
[EditorRequired]
98-
#endif
9997
public ITableColumn? Column { get; set; }
10098

10199
/// <summary>
@@ -132,20 +130,11 @@ public partial class TableFilter : IFilter
132130
[NotNull]
133131
private IIconTheme? IconTheme { get; set; }
134132

135-
[Inject]
136-
[NotNull]
137-
private ILookupService? LookupService { get; set; }
138-
139133
/// <summary>
140134
/// 组件步长
141135
/// </summary>
142136
private string? _step;
143137

144-
/// <summary>
145-
/// 外键数据源集合
146-
/// </summary>
147-
private Lazy<IEnumerable<SelectedItem>?> _lookup = default!;
148-
149138
/// <summary>
150139
/// <inheritdoc/>
151140
/// </summary>
@@ -156,8 +145,6 @@ protected override void OnInitialized()
156145
_title = Column.GetDisplayName();
157146
FieldKey = Column.GetFieldName();
158147
Column.Filter = this;
159-
160-
_lookup = new(() => Column.Lookup ?? LookupService.GetItemsByKey(Column.LookupServiceKey, Column.LookupServiceData));
161148
_step = Column.Step;
162149
}
163150

0 commit comments

Comments
 (0)