Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
<h4>@Localizer["Intro"]</h4>

<DemoBlock Title="@Localizer["NormalTitle"]" Introduction="@Localizer["NormalIntro"]" Name="Normal">
<SelectObject @bind-Value="_value" GetTextCallback="GetTextCallback">
<section ignore>
@((MarkupString)Localizer["NormalDesc"].Value)
</section>
<SelectObject @bind-Value="_value" GetTextCallback="GetTextCallback" IsClearable>
<ListView TItem="ListViews.Product" Items="@Products" OnListViewItemClick="item => OnListViewItemClick(item, context)">
<BodyTemplate Context="value">
<Card>
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 @@ -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 <code>ListView</code> component to select images",
"NormalDesc": "You can use <code>IsClearable</code> to control whether to display the clear button. The default value is <code>false</code>",
"MinWidthTitle": "Min-Width",
"MinWidthIntro": "Change the minimum width of the dropdown box by setting the <code>DropdownMinWidth</code> value",
"HeightTitle": "Height",
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 @@ -6599,6 +6599,7 @@
"Intro": "下拉框为任意组件用于展示复杂类型的选择需求",
"NormalTitle": "基本功能",
"NormalIntro": "内置 <code>ListView</code> 组件选择图片",
"NormalDesc": "可通过 <code>IsClearable</code> 控制是否显示清除小按钮,默认值 <code>false</code>",
"MinWidthTitle": "设置最小宽度",
"MinWidthIntro": "通过设置 <code>DropdownMinWidth</code> 值,来改变下拉框最小宽度",
"HeightTitle": "设置高度",
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.7-beta01</Version>
<Version>9.2.7-beta02</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
4 changes: 4 additions & 0 deletions src/BootstrapBlazor/Components/Select/SelectObject.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>
}
<div class="dropdown-menu dropdown-object" style="@GetStyleString">
@ChildContent(_context)
</div>
Expand Down
40 changes: 40 additions & 0 deletions src/BootstrapBlazor/Components/Select/SelectObject.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ public partial class SelectObject<TItem>
[NotNull]
public string? DropdownIcon { get; set; }

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

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

/// <summary>
/// 获得/设置 下拉列表内容模板
/// </summary>
Expand All @@ -66,6 +79,7 @@ public partial class SelectObject<TItem>
/// </summary>
private string? ClassName => CssBuilder.Default("select select-object dropdown")
.AddClass("disabled", IsDisabled)
.AddClass("cls", IsClearable)
.AddClassFromAttributes(AdditionalAttributes)
.Build();

Expand All @@ -89,6 +103,12 @@ public partial class SelectObject<TItem>
.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();

/// <summary>
/// 获得 PlaceHolder 属性
/// </summary>
Expand All @@ -107,6 +127,12 @@ public partial class SelectObject<TItem>
[Parameter]
public RenderFragment<TItem>? Template { get; set; }

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

[Inject]
[NotNull]
private IStringLocalizer<Select<TItem>>? Localizer { get; set; }
Expand Down Expand Up @@ -151,6 +177,7 @@ protected override void OnParametersSet()

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

/// <summary>
Expand All @@ -159,6 +186,8 @@ protected override void OnParametersSet()
/// <returns></returns>
protected override bool IsRequired() => ValidateForm != null;

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

/// <summary>
/// 获得 Text 显示文字
/// </summary>
Expand All @@ -170,4 +199,15 @@ protected override void OnParametersSet()
/// </summary>
/// <returns></returns>
public Task CloseAsync() => InvokeVoidAsync("close", Id);

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

Value = default;
await CloseAsync();
}
}
29 changes: 29 additions & 0 deletions test/UnitTest/Components/SelectObjectTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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]
Expand Down Expand Up @@ -182,6 +204,7 @@ public async Task Validate_Ok()
builder.Add(a => a.Model, model);
builder.AddChildContent<SelectObject<string>>(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 =>
Expand All @@ -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<SelectObject<string>>();
table.SetParametersAndRender();
Expand All @@ -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
Expand Down
Loading