Skip to content

Commit a69614f

Browse files
refactor(AutoFill): add IsLikeMatch/IgnoreCase parameter (#5014)
* feat: 增加 IsLikeMatch IgnoreCase 参数 * refactor: 增加 Value 空判断 * doc: 精简代码 * test: 增加单元测试 * test: 更新单元测试 * chore: 更新依赖 9.1.5 Co-Authored-By: Alex chow <[email protected]>
1 parent c9a3d03 commit a69614f

File tree

4 files changed

+92
-9
lines changed

4 files changed

+92
-9
lines changed

src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
<PackageReference Include="BootstrapBlazor.Markdown" Version="9.0.0" />
4747
<PackageReference Include="BootstrapBlazor.MaterialDesign" Version="9.0.0" />
4848
<PackageReference Include="BootstrapBlazor.MaterialDesign.Extensions" Version="9.1.0" />
49-
<PackageReference Include="BootstrapBlazor.MeiliSearch" Version="9.1.4" />
49+
<PackageReference Include="BootstrapBlazor.MeiliSearch" Version="9.1.5" />
5050
<PackageReference Include="BootstrapBlazor.Mermaid" Version="9.0.3" />
5151
<PackageReference Include="BootstrapBlazor.MindMap" Version="9.1.1" />
5252
<PackageReference Include="BootstrapBlazor.MouseFollower" Version="9.0.1" />

src/BootstrapBlazor.Server/Components/Samples/InputGroups.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@
8888
<div class="col-12 col-sm-6">
8989
<BootstrapInputGroup>
9090
<BootstrapInputGroupLabel DisplayText="AutoFill" />
91-
<AutoFill TValue="Foo" Items="AufoFillItems" IsLikeMatch="true" OnGetDisplayText="@(foo => foo.Name ?? "")">
91+
<AutoFill Items="AufoFillItems" IsLikeMatch="true" OnGetDisplayText="@(foo => foo.Name)">
9292
<ItemTemplate>
9393
<div class="d-flex">
9494
<div>

src/BootstrapBlazor/Components/AutoFill/AutoFill.razor.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@ public partial class AutoFill<TValue>
3939
[NotNull]
4040
public int? DisplayCount { get; set; }
4141

42+
/// <summary>
43+
/// 获得/设置 是否开启模糊查询,默认为 false
44+
/// </summary>
45+
[Parameter]
46+
public bool IsLikeMatch { get; set; }
47+
48+
/// <summary>
49+
/// 获得/设置 匹配时是否忽略大小写,默认为 true
50+
/// </summary>
51+
[Parameter]
52+
public bool IgnoreCase { get; set; } = true;
53+
4254
/// <summary>
4355
/// 获得/设置 获得焦点时是否展开下拉候选菜单 默认 true
4456
/// </summary>
@@ -108,7 +120,7 @@ protected override void OnParametersSet()
108120
LoadingIcon ??= IconTheme.GetIconByKey(ComponentIcons.LoadingIcon);
109121

110122
OnGetDisplayText ??= v => v?.ToString();
111-
_displayText = OnGetDisplayText(Value);
123+
_displayText = Value is null ? "" : OnGetDisplayText(Value);
112124

113125
FilterItems ??= Items?.ToList() ?? [];
114126
}
@@ -139,6 +151,14 @@ public async Task TriggerOnChange(string val)
139151
var items = await OnCustomFilter(val);
140152
FilterItems = items.ToList();
141153
}
154+
else
155+
{
156+
var comparisionType = IgnoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
157+
FilterItems = IsLikeMatch
158+
? Items.Where(i => OnGetDisplayText(i)?.Contains(val, comparisionType) ?? false).ToList()
159+
: Items.Where(i => OnGetDisplayText(i)?.StartsWith(val, comparisionType) ?? false).ToList();
160+
}
161+
142162
if (DisplayCount != null)
143163
{
144164
FilterItems = FilterItems.Take(DisplayCount.Value).ToList();

test/UnitTest/Components/AutoFillTest.cs

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,33 +157,96 @@ public async Task OnSelectedItemChanged_Ok()
157157
}
158158

159159
[Fact]
160-
public void OnGetDisplayText_Ok()
160+
public async Task OnGetDisplayText_Ok()
161161
{
162162
var cut = Context.RenderComponent<AutoFill<Foo>>(pb =>
163163
{
164164
pb.Add(a => a.Value, Model);
165-
pb.Add(a => a.Items, Items);
166-
pb.Add(a => a.OnGetDisplayText, foo => foo.Name);
165+
pb.Add(a => a.Items, new List<Foo> { null!, new() { Name = "Test" } });
166+
pb.Add(a => a.OnGetDisplayText, foo => foo?.Name);
167167
});
168168
var input = cut.Find("input");
169169
Assert.Equal("张三 1000", input.Attributes["value"]?.Value);
170+
171+
cut.SetParametersAndRender(pb =>
172+
{
173+
pb.Add(a => a.OnGetDisplayText, null!);
174+
});
175+
await cut.InvokeAsync(() => cut.Instance.TriggerOnChange("t"));
176+
177+
cut.SetParametersAndRender(pb =>
178+
{
179+
pb.Add(a => a.IsLikeMatch, true);
180+
});
181+
await cut.InvokeAsync(() => cut.Instance.TriggerOnChange("t"));
170182
}
171183

172184
[Fact]
173-
public async Task DisplayCount_Ok()
185+
public async Task IgnoreCase_Ok()
174186
{
175-
var items = new List<Foo>() { new() { Name = "task1" }, new() { Name = "Task2" }, new() { Name = "task3" }, new() { Name = "Task4" } };
187+
var items = new List<Foo>() { new() { Name = "task1" }, new() { Name = "task2" }, new() { Name = "Task3" }, new() { Name = "Task4" } };
176188
var cut = Context.RenderComponent<AutoFill<Foo>>(builder =>
177189
{
178190
builder.Add(a => a.Items, items);
179-
builder.Add(a => a.DisplayCount, 2);
191+
builder.Add(a => a.IgnoreCase, true);
192+
builder.Add(a => a.OnGetDisplayText, foo => foo.Name);
180193
});
181194

182195
await cut.InvokeAsync(() => cut.Instance.TriggerOnChange("t"));
183196
var menus = cut.FindAll(".dropdown-item");
197+
Assert.Equal(4, menus.Count);
198+
199+
cut.SetParametersAndRender(pb =>
200+
{
201+
pb.Add(a => a.DisplayCount, 2);
202+
});
203+
await cut.InvokeAsync(() => cut.Instance.TriggerOnChange("t"));
204+
menus = cut.FindAll(".dropdown-item");
205+
Assert.Equal(2, menus.Count);
206+
207+
cut.SetParametersAndRender(pb =>
208+
{
209+
pb.Add(a => a.IgnoreCase, false);
210+
pb.Add(a => a.DisplayCount, null);
211+
});
212+
await cut.InvokeAsync(() => cut.Instance.TriggerOnChange("t"));
213+
menus = cut.FindAll(".dropdown-item");
184214
Assert.Equal(2, menus.Count);
185215
}
186216

217+
[Fact]
218+
public async Task IsLikeMatch_Ok()
219+
{
220+
var items = new List<Foo>() { new() { Name = "task1" }, new() { Name = "task2" }, new() { Name = "Task3" }, new() { Name = "Task4" } };
221+
var cut = Context.RenderComponent<AutoFill<Foo>>(builder =>
222+
{
223+
builder.Add(a => a.Items, items);
224+
builder.Add(a => a.IsLikeMatch, false);
225+
builder.Add(a => a.OnGetDisplayText, foo => foo.Name);
226+
});
227+
228+
await cut.InvokeAsync(() => cut.Instance.TriggerOnChange("t"));
229+
var menus = cut.FindAll(".dropdown-item");
230+
Assert.Equal(4, menus.Count);
231+
232+
cut.SetParametersAndRender(pb =>
233+
{
234+
pb.Add(a => a.DisplayCount, 2);
235+
});
236+
await cut.InvokeAsync(() => cut.Instance.TriggerOnChange("t"));
237+
menus = cut.FindAll(".dropdown-item");
238+
Assert.Equal(2, menus.Count);
239+
240+
cut.SetParametersAndRender(pb =>
241+
{
242+
pb.Add(a => a.IsLikeMatch, true);
243+
pb.Add(a => a.DisplayCount, null);
244+
});
245+
await cut.InvokeAsync(() => cut.Instance.TriggerOnChange("a"));
246+
menus = cut.FindAll(".dropdown-item");
247+
Assert.Equal(4, menus.Count);
248+
}
249+
187250
[Fact]
188251
public void ShowDropdownListOnFocus_Ok()
189252
{

0 commit comments

Comments
 (0)