Skip to content

Commit a46e51d

Browse files
authored
feat(SelectGeneric): add SelectGeneric component (#4838)
* refactor: 重构 SelectedItem 增加构造函数 * refactor: 移动 SelectedItem 到子类 * refactor: 精简代码移除 SingleSelectBase 类 * refactor: 改造 SelectedItem 泛型 * feat: 增加 SelectGeneric 组件 * feat: 增加 ToSelectList 泛型扩展方法 * refactor: 改造 Select 组件移除对泛型的支持 * doc: 更新泛型 Select 组件示例 * test: 更新单元测试 * test: 更新单元测试 * refactor: 增加排除标签 * chore: bump version 9.1.3-beta06 * test: 增加单元测试 * test: 更新单元测试 * test: 增加 Display 单元测试 * test: 更新 Select 单元测试 * refactor: 更新 SelectGeneric 值不存在时的逻辑
1 parent a21ae6a commit a46e51d

21 files changed

+1432
-287
lines changed

src/BootstrapBlazor.Shared/Components/Samples/Selects.razor

+1-1
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@
442442
<section ignore>@((MarkupString)Localizer["SelectsGenericDesc"].Value)</section>
443443
<div class="row">
444444
<div class="col-12 col-sm-6">
445-
<Select Items="_genericItems" @bind-Value="_selectedFoo" IsEditable="true"></Select>
445+
<SelectGeneric Items="_genericItems" @bind-Value="_selectedFoo" IsEditable="true"></SelectGeneric>
446446
</div>
447447
<div class="col-12 col-sm-6">
448448
<Display Value="_selectedFoo?.Address"></Display>

src/BootstrapBlazor.Shared/Components/Samples/Selects.razor.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ private Task OnTimeZoneValueChanged(string timeZoneId)
242242
return Task.CompletedTask;
243243
}
244244

245-
private readonly List<SelectedItem<Foo>> _genericItems =
245+
private readonly List<SelectedItem<Foo?>> _genericItems =
246246
[
247247
new() { Text = "Foo1", Value = new Foo() { Id = 1, Address = "Address_F001" } },
248248
new() { Text = "Foo2", Value = new Foo() { Id = 2, Address = "Address_F002" } },

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-beta05</Version>
4+
<Version>9.1.3-beta06</Version>
55
</PropertyGroup>
66

77
<ItemGroup>

src/BootstrapBlazor/Components/Select/MultiSelect.razor.cs

+13
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,19 @@ public partial class MultiSelect<TValue>
3636
.AddClass("d-none", SelectedItems.Count != 0)
3737
.Build();
3838

39+
/// <summary>
40+
/// 获得/设置 绑定数据集
41+
/// </summary>
42+
[Parameter]
43+
[NotNull]
44+
public IEnumerable<SelectedItem>? Items { get; set; }
45+
46+
/// <summary>
47+
/// 获得/设置 选项模板
48+
/// </summary>
49+
[Parameter]
50+
public RenderFragment<SelectedItem>? ItemTemplate { get; set; }
51+
3952
/// <summary>
4053
/// 获得/设置 组件 PlaceHolder 文字 默认为 点击进行多选 ...
4154
/// </summary>

src/BootstrapBlazor/Components/Select/Select.razor

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@namespace BootstrapBlazor.Components
22
@using Microsoft.AspNetCore.Components.Web.Virtualization
33
@typeparam TValue
4-
@inherits SingleSelectBase<TValue>
4+
@inherits SelectBase<TValue>
55
@attribute [BootstrapModuleAutoLoader(JSObjectReference = true)]
66

77
@if (IsShowLabel)

src/BootstrapBlazor/Components/Select/Select.razor.cs

+61-36
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace BootstrapBlazor.Components;
1212
/// Select 组件实现类
1313
/// </summary>
1414
/// <typeparam name="TValue"></typeparam>
15+
[ExcludeFromCodeCoverage]
1516
public partial class Select<TValue> : ISelect, IModelEqualityComparer<TValue>
1617
{
1718
[Inject]
@@ -50,7 +51,7 @@ public partial class Select<TValue> : ISelect, IModelEqualityComparer<TValue>
5051
/// <param name="item"></param>
5152
/// <returns></returns>
5253
private string? ActiveItem(SelectedItem item) => CssBuilder.Default("dropdown-item")
53-
.AddClass("active", Match(item))
54+
.AddClass("active", item.Value == CurrentValueAsString)
5455
.AddClass("disabled", item.IsDisabled)
5556
.Build();
5657

@@ -191,6 +192,55 @@ public partial class Select<TValue> : ISelect, IModelEqualityComparer<TValue>
191192
[NotNull]
192193
private Virtualize<SelectedItem>? VirtualizeElement { get; set; }
193194

195+
/// <summary>
196+
/// 获得/设置 绑定数据集
197+
/// </summary>
198+
[Parameter]
199+
[NotNull]
200+
public IEnumerable<SelectedItem>? Items { get; set; }
201+
202+
/// <summary>
203+
/// 获得/设置 选项模板
204+
/// </summary>
205+
[Parameter]
206+
public RenderFragment<SelectedItem>? ItemTemplate { get; set; }
207+
208+
/// <summary>
209+
/// 获得/设置 下拉框项目改变前回调委托方法 返回 true 时选项值改变,否则选项值不变
210+
/// </summary>
211+
[Parameter]
212+
public Func<SelectedItem, Task<bool>>? OnBeforeSelectedItemChange { get; set; }
213+
214+
/// <summary>
215+
/// SelectedItemChanged 回调方法
216+
/// </summary>
217+
[Parameter]
218+
public Func<SelectedItem, Task>? OnSelectedItemChanged { get; set; }
219+
220+
/// <summary>
221+
/// 获得/设置 Swal 图标 默认 Question
222+
/// </summary>
223+
[Parameter]
224+
public SwalCategory SwalCategory { get; set; } = SwalCategory.Question;
225+
226+
/// <summary>
227+
/// 获得/设置 Swal 标题 默认 null
228+
/// </summary>
229+
[Parameter]
230+
public string? SwalTitle { get; set; }
231+
232+
/// <summary>
233+
/// 获得/设置 Swal 内容 默认 null
234+
/// </summary>
235+
[Parameter]
236+
public string? SwalContent { get; set; }
237+
238+
/// <summary>
239+
/// 获得/设置 Footer 默认 null
240+
/// </summary>
241+
[Parameter]
242+
public string? SwalFooter { get; set; }
243+
194244
[Inject]
195245
[NotNull]
196246
private IStringLocalizer<Select<TValue>>? Localizer { get; set; }
@@ -214,6 +264,11 @@ public partial class Select<TValue> : ISelect, IModelEqualityComparer<TValue>
214264

215265
private ItemsProviderResult<SelectedItem> _result;
216266

267+
/// <summary>
268+
/// 当前选择项实例
269+
/// </summary>
270+
private SelectedItem? SelectedItem { get; set; }
271+
217272
private List<SelectedItem> Rows
218273
{
219274
get
@@ -234,7 +289,7 @@ private SelectedItem? SelectedRow
234289

235290
private SelectedItem? GetSelectedRow()
236291
{
237-
var item = Rows.Find(Match)
292+
var item = Rows.Find(i => i.Value == CurrentValueAsString)
238293
?? Rows.Find(i => i.Active)
239294
?? Rows.Where(i => !i.IsDisabled).FirstOrDefault()
240295
?? GetVirtualizeItem();
@@ -374,8 +429,6 @@ private bool TryParseSelectItem(string value, [MaybeNullWhen(false)] out TValue
374429
/// <returns></returns>
375430
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, nameof(ConfirmSelectedItem));
376431

377-
private bool Match(SelectedItem i) => i is SelectedItem<TValue> d ? Equals(d.Value, Value) : i.Value.Equals(CurrentValueAsString, StringComparison);
378-
379432
/// <summary>
380433
/// 客户端回车回调方法
381434
/// </summary>
@@ -453,13 +506,13 @@ private async Task ValueTypeChanged(SelectedItem item)
453506
{
454507
if (_lastSelectedValueString != item.Value)
455508
{
456-
_lastSelectedValueString = item.Value;
457509

458510
item.Active = true;
459511
SelectedItem = item;
460512

461513
// 触发 StateHasChanged
462-
CurrentValueAsString = item.Value;
514+
_lastSelectedValueString = item.Value ?? "";
515+
CurrentValueAsString = _lastSelectedValueString;
463516

464517
// 触发 SelectedItemChanged 事件
465518
if (OnSelectedItemChanged != null)
@@ -518,41 +571,13 @@ private async Task OnChange(ChangeEventArgs args)
518571

519572
if (item == null)
520573
{
521-
// 判断是否为泛型 SelectedItem
522-
var itemType = Items.GetType();
523-
var isGeneric = false;
524-
if (itemType.IsGenericType)
525-
{
526-
isGeneric = itemType.GetGenericArguments()[0].IsGenericType;
527-
}
528-
if (isGeneric)
529-
{
530-
TValue? val = default;
531-
if (TextConvertToValueCallback != null)
532-
{
533-
val = await TextConvertToValueCallback(v);
534-
}
535-
item = new SelectedItem<TValue>() { Text = v, Value = val };
536-
}
537-
else
538-
{
539-
item = new SelectedItem(v, v);
540-
}
574+
item = new SelectedItem(v, v);
541575

542576
var items = new List<SelectedItem>() { item };
543577
items.AddRange(Items);
544578
Items = items;
545-
CurrentValueAsString = v;
546-
}
547-
548-
if (item is SelectedItem<TValue> value)
549-
{
550-
CurrentValue = value.Value;
551-
}
552-
else
553-
{
554-
CurrentValueAsString = v;
555579
}
580+
CurrentValueAsString = v;
556581

557582
if (OnInputChangedCallback != null)
558583
{

src/BootstrapBlazor/Components/Select/SelectBase.cs

-13
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,6 @@ public abstract class SelectBase<TValue> : PopoverSelectBase<TValue>
1616
[Parameter]
1717
public Color Color { get; set; }
1818

19-
/// <summary>
20-
/// 获得/设置 绑定数据集
21-
/// </summary>
22-
[Parameter]
23-
[NotNull]
24-
public IEnumerable<SelectedItem>? Items { get; set; }
25-
2619
/// <summary>
2720
/// 获得/设置 是否显示搜索框 默认为 false 不显示
2821
/// </summary>
@@ -54,12 +47,6 @@ public abstract class SelectBase<TValue> : PopoverSelectBase<TValue>
5447
[Parameter]
5548
public StringComparison StringComparison { get; set; } = StringComparison.OrdinalIgnoreCase;
5649

57-
/// <summary>
58-
/// 获得/设置 选项模板
59-
/// </summary>
60-
[Parameter]
61-
public RenderFragment<SelectedItem>? ItemTemplate { get; set; }
62-
6350
/// <summary>
6451
/// 获得/设置 分组项模板
6552
/// </summary>

src/BootstrapBlazor/Components/Select/SelectOption.cs

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace BootstrapBlazor.Components;
88
/// <summary>
99
/// SelectOption 组件
1010
/// </summary>
11+
[ExcludeFromCodeCoverage]
1112
public class SelectOption : ComponentBase
1213
{
1314
/// <summary>

src/BootstrapBlazor/Components/Select/SingleSelectBase.cs

-53
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the Apache 2.0 License
3+
// See the LICENSE file in the project root for more information.
4+
// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
5+
6+
namespace BootstrapBlazor.Components;
7+
8+
/// <summary>
9+
/// ISelect 接口
10+
/// </summary>
11+
public interface ISelectGeneric<TValue>
12+
{
13+
/// <summary>
14+
/// 增加 SelectedItem 项方法
15+
/// </summary>
16+
/// <param name="item"></param>
17+
void Add(SelectedItem<TValue> item);
18+
}

0 commit comments

Comments
 (0)