Skip to content

Commit

Permalink
feat(SelectGeneric): add SelectGeneric component (#4838)
Browse files Browse the repository at this point in the history
* 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 值不存在时的逻辑
  • Loading branch information
ArgoZhang authored Dec 13, 2024
1 parent a21ae6a commit a46e51d
Show file tree
Hide file tree
Showing 21 changed files with 1,432 additions and 287 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@
<section ignore>@((MarkupString)Localizer["SelectsGenericDesc"].Value)</section>
<div class="row">
<div class="col-12 col-sm-6">
<Select Items="_genericItems" @bind-Value="_selectedFoo" IsEditable="true"></Select>
<SelectGeneric Items="_genericItems" @bind-Value="_selectedFoo" IsEditable="true"></SelectGeneric>
</div>
<div class="col-12 col-sm-6">
<Display Value="_selectedFoo?.Address"></Display>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ private Task OnTimeZoneValueChanged(string timeZoneId)
return Task.CompletedTask;
}

private readonly List<SelectedItem<Foo>> _genericItems =
private readonly List<SelectedItem<Foo?>> _genericItems =
[
new() { Text = "Foo1", Value = new Foo() { Id = 1, Address = "Address_F001" } },
new() { Text = "Foo2", Value = new Foo() { Id = 2, Address = "Address_F002" } },
Expand Down
2 changes: 1 addition & 1 deletion src/BootstrapBlazor/BootstrapBlazor.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<Version>9.1.3-beta05</Version>
<Version>9.1.3-beta06</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
13 changes: 13 additions & 0 deletions src/BootstrapBlazor/Components/Select/MultiSelect.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,19 @@ public partial class MultiSelect<TValue>
.AddClass("d-none", SelectedItems.Count != 0)
.Build();

/// <summary>
/// 获得/设置 绑定数据集
/// </summary>
[Parameter]
[NotNull]
public IEnumerable<SelectedItem>? Items { get; set; }

/// <summary>
/// 获得/设置 选项模板
/// </summary>
[Parameter]
public RenderFragment<SelectedItem>? ItemTemplate { get; set; }

/// <summary>
/// 获得/设置 组件 PlaceHolder 文字 默认为 点击进行多选 ...
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/BootstrapBlazor/Components/Select/Select.razor
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@namespace BootstrapBlazor.Components
@using Microsoft.AspNetCore.Components.Web.Virtualization
@typeparam TValue
@inherits SingleSelectBase<TValue>
@inherits SelectBase<TValue>
@attribute [BootstrapModuleAutoLoader(JSObjectReference = true)]

@if (IsShowLabel)
Expand Down
97 changes: 61 additions & 36 deletions src/BootstrapBlazor/Components/Select/Select.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace BootstrapBlazor.Components;
/// Select 组件实现类
/// </summary>
/// <typeparam name="TValue"></typeparam>
[ExcludeFromCodeCoverage]
public partial class Select<TValue> : ISelect, IModelEqualityComparer<TValue>
{
[Inject]
Expand Down Expand Up @@ -50,7 +51,7 @@ public partial class Select<TValue> : ISelect, IModelEqualityComparer<TValue>
/// <param name="item"></param>
/// <returns></returns>
private string? ActiveItem(SelectedItem item) => CssBuilder.Default("dropdown-item")
.AddClass("active", Match(item))
.AddClass("active", item.Value == CurrentValueAsString)
.AddClass("disabled", item.IsDisabled)
.Build();

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

/// <summary>
/// 获得/设置 绑定数据集
/// </summary>
[Parameter]
[NotNull]
public IEnumerable<SelectedItem>? Items { get; set; }

/// <summary>
/// 获得/设置 选项模板
/// </summary>
[Parameter]
public RenderFragment<SelectedItem>? ItemTemplate { get; set; }

/// <summary>
/// 获得/设置 下拉框项目改变前回调委托方法 返回 true 时选项值改变,否则选项值不变
/// </summary>
[Parameter]
public Func<SelectedItem, Task<bool>>? OnBeforeSelectedItemChange { get; set; }

/// <summary>
/// SelectedItemChanged 回调方法
/// </summary>
[Parameter]
public Func<SelectedItem, Task>? OnSelectedItemChanged { get; set; }

/// <summary>
/// 获得/设置 Swal 图标 默认 Question
/// </summary>
[Parameter]
public SwalCategory SwalCategory { get; set; } = SwalCategory.Question;

/// <summary>
/// 获得/设置 Swal 标题 默认 null
/// </summary>
[Parameter]
public string? SwalTitle { get; set; }

/// <summary>
/// 获得/设置 Swal 内容 默认 null
/// </summary>
[Parameter]
public string? SwalContent { get; set; }

/// <summary>
/// 获得/设置 Footer 默认 null
/// </summary>
[Parameter]
public string? SwalFooter { get; set; }

[Inject]
[NotNull]
private IStringLocalizer<Select<TValue>>? Localizer { get; set; }
Expand All @@ -214,6 +264,11 @@ public partial class Select<TValue> : ISelect, IModelEqualityComparer<TValue>

private ItemsProviderResult<SelectedItem> _result;

/// <summary>
/// 当前选择项实例
/// </summary>
private SelectedItem? SelectedItem { get; set; }

private List<SelectedItem> Rows
{
get
Expand All @@ -234,7 +289,7 @@ private SelectedItem? SelectedRow

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

private bool Match(SelectedItem i) => i is SelectedItem<TValue> d ? Equals(d.Value, Value) : i.Value.Equals(CurrentValueAsString, StringComparison);

/// <summary>
/// 客户端回车回调方法
/// </summary>
Expand Down Expand Up @@ -453,13 +506,13 @@ private async Task ValueTypeChanged(SelectedItem item)
{
if (_lastSelectedValueString != item.Value)
{
_lastSelectedValueString = item.Value;

item.Active = true;
SelectedItem = item;

// 触发 StateHasChanged
CurrentValueAsString = item.Value;
_lastSelectedValueString = item.Value ?? "";
CurrentValueAsString = _lastSelectedValueString;

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

if (item == null)
{
// 判断是否为泛型 SelectedItem
var itemType = Items.GetType();
var isGeneric = false;
if (itemType.IsGenericType)
{
isGeneric = itemType.GetGenericArguments()[0].IsGenericType;
}
if (isGeneric)
{
TValue? val = default;
if (TextConvertToValueCallback != null)
{
val = await TextConvertToValueCallback(v);
}
item = new SelectedItem<TValue>() { Text = v, Value = val };
}
else
{
item = new SelectedItem(v, v);
}
item = new SelectedItem(v, v);

var items = new List<SelectedItem>() { item };
items.AddRange(Items);
Items = items;
CurrentValueAsString = v;
}

if (item is SelectedItem<TValue> value)
{
CurrentValue = value.Value;
}
else
{
CurrentValueAsString = v;
}
CurrentValueAsString = v;

if (OnInputChangedCallback != null)
{
Expand Down
13 changes: 0 additions & 13 deletions src/BootstrapBlazor/Components/Select/SelectBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,6 @@ public abstract class SelectBase<TValue> : PopoverSelectBase<TValue>
[Parameter]
public Color Color { get; set; }

/// <summary>
/// 获得/设置 绑定数据集
/// </summary>
[Parameter]
[NotNull]
public IEnumerable<SelectedItem>? Items { get; set; }

/// <summary>
/// 获得/设置 是否显示搜索框 默认为 false 不显示
/// </summary>
Expand Down Expand Up @@ -54,12 +47,6 @@ public abstract class SelectBase<TValue> : PopoverSelectBase<TValue>
[Parameter]
public StringComparison StringComparison { get; set; } = StringComparison.OrdinalIgnoreCase;

/// <summary>
/// 获得/设置 选项模板
/// </summary>
[Parameter]
public RenderFragment<SelectedItem>? ItemTemplate { get; set; }

/// <summary>
/// 获得/设置 分组项模板
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions src/BootstrapBlazor/Components/Select/SelectOption.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace BootstrapBlazor.Components;
/// <summary>
/// SelectOption 组件
/// </summary>
[ExcludeFromCodeCoverage]
public class SelectOption : ComponentBase
{
/// <summary>
Expand Down
53 changes: 0 additions & 53 deletions src/BootstrapBlazor/Components/Select/SingleSelectBase.cs

This file was deleted.

18 changes: 18 additions & 0 deletions src/BootstrapBlazor/Components/SelectGeneric/ISelectGeneric.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License
// See the LICENSE file in the project root for more information.
// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone

namespace BootstrapBlazor.Components;

/// <summary>
/// ISelect 接口
/// </summary>
public interface ISelectGeneric<TValue>
{
/// <summary>
/// 增加 SelectedItem 项方法
/// </summary>
/// <param name="item"></param>
void Add(SelectedItem<TValue> item);
}
Loading

0 comments on commit a46e51d

Please sign in to comment.