From 4c235ca2c3398959b030e0312de8a3a35b0dc9eb Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Thu, 9 Jan 2025 14:39:09 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20IsClearable=20?= =?UTF-8?q?=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Select/SelectObject.razor | 4 ++ .../Components/Select/SelectObject.razor.cs | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/BootstrapBlazor/Components/Select/SelectObject.razor b/src/BootstrapBlazor/Components/Select/SelectObject.razor index 06065e56f0a..72aab3f0a28 100644 --- a/src/BootstrapBlazor/Components/Select/SelectObject.razor +++ b/src/BootstrapBlazor/Components/Select/SelectObject.razor @@ -31,6 +31,10 @@ } + @if (GetClearable()) + { + + } diff --git a/src/BootstrapBlazor/Components/Select/SelectObject.razor.cs b/src/BootstrapBlazor/Components/Select/SelectObject.razor.cs index 1bb7ec0fb68..bc6bfbe8691 100644 --- a/src/BootstrapBlazor/Components/Select/SelectObject.razor.cs +++ b/src/BootstrapBlazor/Components/Select/SelectObject.razor.cs @@ -46,6 +46,19 @@ public partial class SelectObject [NotNull] public string? DropdownIcon { get; set; } + /// + /// 获得/设置 是否可清除 默认 false + /// + [Parameter] + public bool IsClearable { get; set; } + + /// + /// 获得/设置 右侧清除图标 默认 fa-solid fa-angle-up + /// + [Parameter] + [NotNull] + public string? ClearIcon { get; set; } + /// /// 获得/设置 下拉列表内容模板 /// @@ -66,6 +79,7 @@ public partial class SelectObject /// private string? ClassName => CssBuilder.Default("select select-object dropdown") .AddClass("disabled", IsDisabled) + .AddClass("cls", IsClearable) .AddClassFromAttributes(AdditionalAttributes) .Build(); @@ -89,6 +103,12 @@ public partial class SelectObject .AddClass($"text-danger", IsValid.HasValue && !IsValid.Value) .Build(); + private string? ClearClassString => CssBuilder.Default("clear-icon") + .AddClass($"text-{Color.ToDescriptionString()}", Color != Color.None) + .AddClass($"text-success", IsValid.HasValue && IsValid.Value) + .AddClass($"text-danger", IsValid.HasValue && !IsValid.Value) + .Build(); + /// /// 获得 PlaceHolder 属性 /// @@ -107,6 +127,12 @@ public partial class SelectObject [Parameter] public RenderFragment? Template { get; set; } + /// + /// 获得/设置 清除文本内容 OnClear 回调方法 默认 null + /// + [Parameter] + public Func? OnClearAsync { get; set; } + [Inject] [NotNull] private IStringLocalizer>? Localizer { get; set; } @@ -151,6 +177,7 @@ protected override void OnParametersSet() PlaceHolder ??= Localizer[nameof(PlaceHolder)]; DropdownIcon ??= IconTheme.GetIconByKey(ComponentIcons.SelectDropdownIcon); + ClearIcon ??= IconTheme.GetIconByKey(ComponentIcons.SelectClearIcon); } /// @@ -159,6 +186,8 @@ protected override void OnParametersSet() /// protected override bool IsRequired() => ValidateForm != null; + private bool GetClearable() => IsClearable && !IsDisabled; + /// /// 获得 Text 显示文字 /// @@ -170,4 +199,15 @@ protected override void OnParametersSet() /// /// public Task CloseAsync() => InvokeVoidAsync("close", Id); + + private async Task OnClearValue() + { + if (OnClearAsync != null) + { + await OnClearAsync(); + } + + Value = default; + await CloseAsync(); + } } From f81a27603c3ddd0087cb2481bceb190d978165d4 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Thu, 9 Jan 2025 14:39:17 +0800 Subject: [PATCH 2/4] =?UTF-8?q?doc:=20=E6=9B=B4=E6=96=B0=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Samples/SelectObjects.razor | 5 ++++- src/BootstrapBlazor.Server/Locales/en-US.json | 1 + src/BootstrapBlazor.Server/Locales/zh-CN.json | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/BootstrapBlazor.Server/Components/Samples/SelectObjects.razor b/src/BootstrapBlazor.Server/Components/Samples/SelectObjects.razor index 8b7e09c12ff..4940a4b9656 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/SelectObjects.razor +++ b/src/BootstrapBlazor.Server/Components/Samples/SelectObjects.razor @@ -7,7 +7,10 @@

@Localizer["Intro"]

- +
+ @((MarkupString)Localizer["NormalDesc"].Value) +
+ diff --git a/src/BootstrapBlazor.Server/Locales/en-US.json b/src/BootstrapBlazor.Server/Locales/en-US.json index 04430971451..a730af06088 100644 --- a/src/BootstrapBlazor.Server/Locales/en-US.json +++ b/src/BootstrapBlazor.Server/Locales/en-US.json @@ -6599,6 +6599,7 @@ "Intro": "Dropdown boxes are used to display the selection requirements for complex types for any component", "NormalTitle": "Basic usage", "NormalIntro": "Use built in ListView component to select images", + "NormalDesc": "You can use IsClearable to control whether to display the clear button. The default value is false", "MinWidthTitle": "Min-Width", "MinWidthIntro": "Change the minimum width of the dropdown box by setting the DropdownMinWidth value", "HeightTitle": "Height", diff --git a/src/BootstrapBlazor.Server/Locales/zh-CN.json b/src/BootstrapBlazor.Server/Locales/zh-CN.json index 30571a9b950..bdfc8ab39be 100644 --- a/src/BootstrapBlazor.Server/Locales/zh-CN.json +++ b/src/BootstrapBlazor.Server/Locales/zh-CN.json @@ -6599,6 +6599,7 @@ "Intro": "下拉框为任意组件用于展示复杂类型的选择需求", "NormalTitle": "基本功能", "NormalIntro": "内置 ListView 组件选择图片", + "NormalDesc": "可通过 IsClearable 控制是否显示清除小按钮,默认值 false", "MinWidthTitle": "设置最小宽度", "MinWidthIntro": "通过设置 DropdownMinWidth 值,来改变下拉框最小宽度", "HeightTitle": "设置高度", From 8bd1a51f1ced8aa375e2999c83cf9f697ca9744c Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Thu, 9 Jan 2025 14:39:37 +0800 Subject: [PATCH 3/4] chore: bump version 9.2.7-beta02 --- src/BootstrapBlazor/BootstrapBlazor.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BootstrapBlazor/BootstrapBlazor.csproj b/src/BootstrapBlazor/BootstrapBlazor.csproj index 0ea84b0f811..908fccc2888 100644 --- a/src/BootstrapBlazor/BootstrapBlazor.csproj +++ b/src/BootstrapBlazor/BootstrapBlazor.csproj @@ -1,7 +1,7 @@ - 9.2.7-beta01 + 9.2.7-beta02 From 6cbb29597be2198cb9319d0805c742502ced5799 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Thu, 9 Jan 2025 14:45:21 +0800 Subject: [PATCH 4/4] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/UnitTest/Components/SelectObjectTest.cs | 29 ++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/UnitTest/Components/SelectObjectTest.cs b/test/UnitTest/Components/SelectObjectTest.cs index b90bb029663..583c40c4c7c 100644 --- a/test/UnitTest/Components/SelectObjectTest.cs +++ b/test/UnitTest/Components/SelectObjectTest.cs @@ -48,6 +48,24 @@ public async Task Value_Ok() await cut.InvokeAsync(() => item.Click()); Assert.NotNull(v); Assert.Equal(url, v.ImageUrl); + + var isClear = false; + cut.SetParametersAndRender(pb => + { + pb.Add(a => a.IsClearable, true); + pb.Add(a => a.OnClearAsync, () => + { + isClear = true; + return Task.CompletedTask; + }); + }); + Assert.Contains("clear-icon", cut.Markup); + + var span = cut.Find(".clear-icon"); + await cut.InvokeAsync(() => span.Click()); + var input = cut.Find(".form-select"); + Assert.Null(input.GetAttribute("value")); + Assert.True(isClear); } [Fact] @@ -61,8 +79,12 @@ public void Color_Ok() { pb.AddContent(0, "test"); }); + pb.Add(a => a.IsClearable, true); }); cut.Contains("border-danger"); + + var span = cut.Find(".clear-icon"); + Assert.True(span.ClassList.Contains("text-danger")); } [Fact] @@ -182,6 +204,7 @@ public async Task Validate_Ok() builder.Add(a => a.Model, model); builder.AddChildContent>(pb => { + pb.Add(a => a.IsClearable, true); pb.Add(a => a.Value, model.Name); pb.Add(a => a.ValueExpression, Utility.GenerateValueExpression(model, "Name", typeof(string))); pb.Add(a => a.OnValueChanged, v => @@ -205,6 +228,9 @@ await cut.InvokeAsync(() => }); Assert.True(valid); + var span = cut.Find(".clear-icon"); + Assert.True(span.ClassList.Contains("text-success")); + model.Name = null; var table = cut.FindComponent>(); table.SetParametersAndRender(); @@ -214,6 +240,9 @@ await cut.InvokeAsync(() => form.Submit(); }); Assert.True(invalid); + + span = cut.Find(".clear-icon"); + Assert.True(span.ClassList.Contains("text-danger")); } class Product