Skip to content

Commit

Permalink
feat(SelectTable): add IsClearable parameter (#5074)
Browse files Browse the repository at this point in the history
* feat: 增加 IsClearable 参数

* style: 更新样式

* doc: 更新示例

* chore: bump version 9.2.7-beta01

* test: 增加单元测试

* test: 更新单元测试
  • Loading branch information
ArgoZhang authored Jan 9, 2025
1 parent 68ddec2 commit 6113b85
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
<h4>@Localizer["Intro"]</h4>

<DemoBlock Title="@Localizer["NormalTitle"]" Introduction="@Localizer["NormalIntro"]" Name="Normal">
<SelectTable TItem="Foo" @bind-Value="@_foo" OnQueryAsync="OnQueryAsync" GetTextCallback="@GetTextCallback" TableMinWidth="300">
<section ignore>
@((MarkupString)Localizer["NormalDesc"].Value)
</section>
<SelectTable TItem="Foo" @bind-Value="@_foo" OnQueryAsync="OnQueryAsync" GetTextCallback="@GetTextCallback" TableMinWidth="300" IsClearable>
<TableColumns>
<TableColumn @bind-Field="@context.Name"></TableColumn>
<TableColumn @bind-Field="@context.Address"></TableColumn>
Expand Down
1 change: 1 addition & 0 deletions src/BootstrapBlazor.Server/Locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -6567,6 +6567,7 @@
"Intro": "The dropdown box is a table used to display the selection requirements for complex types",
"NormalTitle": "Basic usage",
"NormalIntro": "Suitable for candidates with a relatively large amount of information, presenting information using <code>Table</code>",
"NormalDesc": "You can use <code>IsClearable</code> to control whether to display the clear button. The default value is <code>false</code>",
"ColorTitle": "Color",
"ColorIntro": "Change component border color by setting <code>Color</code>",
"IsDisabledTitle": "Disabled",
Expand Down
1 change: 1 addition & 0 deletions src/BootstrapBlazor.Server/Locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -6567,6 +6567,7 @@
"Intro": "下拉框为表格用于展示复杂类型的选择需求",
"NormalTitle": "基本功能",
"NormalIntro": "适用于候选项信息量比较大,用 <code>Table</code> 呈现信息量",
"NormalDesc": "可通过 <code>IsClearable</code> 控制是否显示清除小按钮,默认值 <code>false</code>",
"ColorTitle": "颜色",
"ColorIntro": "通过设置 <code>Color</code> 改变组件边框颜色",
"IsDisabledTitle": "禁用",
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.2.6</Version>
<Version>9.2.7-beta01</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
36 changes: 19 additions & 17 deletions src/BootstrapBlazor/Components/Select/Select.razor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -147,25 +147,27 @@
transform: rotate(0);
}

.select .clear-icon {
position: absolute;
height: 100%;
width: var(--bb-select-append-width);
right: 0;
top: 0;
color: var(--bb-select-append-color);
align-items: center;
justify-content: center;
cursor: pointer;
display: none;
}
.select {
.clear-icon {
position: absolute;
height: 100%;
width: var(--bb-select-append-width);
right: 0;
top: 0;
color: var(--bb-select-append-color);
align-items: center;
justify-content: center;
cursor: pointer;
display: none;
}

.select:hover .clear-icon {
display: flex;
}
&:hover .clear-icon {
display: flex;
}

.select.cls:hover .form-select-append {
display: none;
&.cls:hover .form-select-append {
display: none;
}
}

.form-select.is-valid:focus,
Expand Down
4 changes: 4 additions & 0 deletions src/BootstrapBlazor/Components/Select/SelectTable.razor
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
<span class="@AppendClassString"><i class="@DropdownIcon"></i></span>
}
</div>
@if (GetClearable())
{
<span class="@ClearClassString" @onclick="OnClearValue"><i class="@ClearIcon"></i></span>
}
<CascadingValue Value="this" IsFixed="true">
@TableColumns?.Invoke(new TItem())
</CascadingValue>
Expand Down
39 changes: 39 additions & 0 deletions src/BootstrapBlazor/Components/Select/SelectTable.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ namespace BootstrapBlazor.Components;
[NotNull]
public string? DropdownIcon { get; set; }

/// <summary>
/// 获得/设置 是否可清除 默认 false
/// </summary>
[Parameter]
public bool IsClearable { get; set; }

/// <summary>
/// 获得/设置 IIconTheme 服务实例
/// </summary>
Expand All @@ -78,6 +84,7 @@ namespace BootstrapBlazor.Components;
/// </summary>
private string? ClassName => CssBuilder.Default("select select-table dropdown")
.AddClass("disabled", IsDisabled)
.AddClass("cls", IsClearable)
.AddClassFromAttributes(AdditionalAttributes)
.Build();

Expand All @@ -101,6 +108,15 @@ namespace BootstrapBlazor.Components;
.AddClass($"text-danger", IsValid.HasValue && !IsValid.Value)
.Build();

private bool GetClearable() => IsClearable && !IsDisabled;

/// <summary>
/// 获得/设置 右侧清除图标 默认 fa-solid fa-angle-up
/// </summary>
[Parameter]
[NotNull]
public string? ClearIcon { get; set; }

/// <summary>
/// 获得 PlaceHolder 属性
/// </summary>
Expand Down Expand Up @@ -174,6 +190,12 @@ namespace BootstrapBlazor.Components;
[Parameter]
public bool AutoGenerateColumns { get; set; }

/// <summary>
/// 获得/设置 清除文本内容 OnClear 回调方法 默认 null
/// </summary>
[Parameter]
public Func<Task>? OnClearAsync { get; set; }

[Inject]
[NotNull]
private IStringLocalizer<Select<TItem>>? Localizer { get; set; }
Expand All @@ -191,6 +213,12 @@ namespace BootstrapBlazor.Components;

private string GetStyleString => $"height: {Height}px;";

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();

/// <summary>
/// <inheritdoc/>
/// </summary>
Expand Down Expand Up @@ -220,6 +248,7 @@ protected override void OnParametersSet()

PlaceHolder ??= Localizer[nameof(PlaceHolder)];
DropdownIcon ??= IconTheme.GetIconByKey(ComponentIcons.SelectDropdownIcon);
ClearIcon ??= IconTheme.GetIconByKey(ComponentIcons.SelectClearIcon);
}

/// <summary>
Expand All @@ -239,4 +268,14 @@ private async Task OnClickRowCallback(TItem item)
CurrentValue = item;
await InvokeVoidAsync("close", Id);
}

private async Task OnClearValue()
{
if (OnClearAsync != null)
{
await OnClearAsync();
}

await OnClickRowCallback(default!);
}
}
49 changes: 49 additions & 0 deletions test/UnitTest/Components/SelectTableTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,44 @@ public void Items_Ok()
});
}

[Fact]
public async Task IsClearable_Ok()
{
var localizer = Context.Services.GetRequiredService<IStringLocalizer<Foo>>();
var items = Foo.GenerateFoo(localizer, 4);
var cut = Context.RenderComponent<BootstrapBlazorRoot>(pb =>
{
pb.AddChildContent<SelectTable<Foo>>(pb =>
{
pb.Add(a => a.OnQueryAsync, options => OnFilterQueryAsync(options, items));
pb.Add(a => a.GetTextCallback, foo => foo.Name);
});
});
var table = cut.FindComponent<SelectTable<Foo>>();
Assert.DoesNotContain("clear-icon", table.Markup);

var isClear = false;
table.SetParametersAndRender(pb =>
{
pb.Add(a => a.IsClearable, true);
pb.Add(a => a.Value, items[0]);
pb.Add(a => a.OnClearAsync, () =>
{
isClear = true;
return Task.CompletedTask;
});
});
Assert.Contains("clear-icon", table.Markup);
var input = table.Find(".form-select");
Assert.Equal("张三 0001", input.GetAttribute("value"));

var span = table.Find(".clear-icon");
await table.InvokeAsync(() => span.Click());
input = table.Find(".form-select");
Assert.Null(input.GetAttribute("value"));
Assert.True(isClear);
}

[Fact]
public void TableMinWidth_Ok()
{
Expand Down Expand Up @@ -65,9 +103,13 @@ public void Color_Ok()
pb.Add(a => a.Color, Color.Danger);
pb.Add(a => a.GetTextCallback, foo => foo.Name);
pb.Add(a => a.OnQueryAsync, options => OnFilterQueryAsync(options, items));
pb.Add(a => a.IsClearable, true);
});
});
cut.Contains("border-danger");

var span = cut.Find(".clear-icon");
Assert.True(span.ClassList.Contains("text-danger"));
}

[Fact]
Expand Down Expand Up @@ -271,6 +313,7 @@ public async Task Validate_Ok()
builder.Add(a => a.Model, model);
builder.AddChildContent<SelectTable<Foo>>(pb =>
{
pb.Add(a => a.IsClearable, true);
pb.Add(a => a.Value, model.Foo);
pb.Add(a => a.ValueExpression, Utility.GenerateValueExpression(model, "Foo", typeof(Foo)));
pb.Add(a => a.OnValueChanged, v =>
Expand Down Expand Up @@ -302,6 +345,9 @@ await cut.InvokeAsync(() =>
});
Assert.True(valid);

var span = cut.Find(".clear-icon");
Assert.True(span.ClassList.Contains("text-success"));

model.Foo = null;
var table = cut.FindComponent<SelectTable<Foo>>();
table.SetParametersAndRender();
Expand All @@ -311,6 +357,9 @@ await cut.InvokeAsync(() =>
form.Submit();
});
Assert.True(invalid);

span = cut.Find(".clear-icon");
Assert.True(span.ClassList.Contains("text-danger"));
}

[Fact]
Expand Down

0 comments on commit 6113b85

Please sign in to comment.