Skip to content

Commit f96b827

Browse files
authored
feat(SelectGeneric): add SelectGeneric component (#4846)
* feat: 增加 SelectGeneric 组件 * test: 增加单元测试 * chore: bump version 9.1.3-beta08 * fix: 修复禁用后无法展开下拉框问题 * feat: 增加 Item 禁用样式 * test: 增加单元测试
1 parent 41dbb19 commit f96b827

File tree

12 files changed

+2162
-29
lines changed

12 files changed

+2162
-29
lines changed

src/BootstrapBlazor/BootstrapBlazor.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk.Razor">
22

33
<PropertyGroup>
4-
<Version>9.1.3-beta07</Version>
4+
<Version>9.1.3-beta08</Version>
55
</PropertyGroup>
66

77
<ItemGroup>

src/BootstrapBlazor/Components/Dropdown/Dropdown.razor

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,31 +22,28 @@
2222
{
2323
<button type="button" class="@ClassName" data-bs-toggle="@ToggleString" disabled="@Disabled" aria-haspopup="true" aria-expanded="false"></button>
2424
}
25-
@if (!IsDisabled)
26-
{
27-
<div class="@MenuAlignmentClass">
28-
@if (ItemsTemplate == null)
25+
<div class="@MenuAlignmentClass">
26+
@if (ItemsTemplate == null)
27+
{
28+
@foreach (var item in GetItems())
2929
{
30-
@foreach (var item in GetItems())
30+
if (ItemTemplate != null)
3131
{
32-
if (ItemTemplate != null)
33-
{
34-
@ItemTemplate.Invoke(item)
35-
}
36-
else if (item.IsDisabled)
37-
{
38-
<div class="@ActiveItem(item)">@item.Text</div>
39-
}
40-
else
41-
{
42-
<div class="@ActiveItem(item)" @onclick="e => OnItemClick(item)">@item.Text</div>
43-
}
32+
@ItemTemplate.Invoke(item)
33+
}
34+
else if (item.IsDisabled)
35+
{
36+
<div class="@DisableItem(item)">@item.Text</div>
37+
}
38+
else
39+
{
40+
<div class="@ActiveItem(item)" @onclick="e => OnItemClick(item)">@item.Text</div>
4441
}
4542
}
46-
else
47-
{
48-
@ItemsTemplate
49-
}
50-
</div>
51-
}
43+
}
44+
else
45+
{
46+
@ItemsTemplate
47+
}
48+
</div>
5249
</div>

src/BootstrapBlazor/Components/Dropdown/Dropdown.razor.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ public partial class Dropdown<TValue>
6262
.AddClass("active", () => item.Value == CurrentValueAsString)
6363
.Build();
6464

65+
/// <summary>
66+
/// 获得/设置 设置当前项是否 Active 方法
67+
/// </summary>
68+
/// <param name="item"></param>
69+
/// <returns></returns>
70+
protected string? DisableItem(SelectedItem item) => CssBuilder.Default("dropdown-item")
71+
.AddClass("is-disabled", item.IsDisabled)
72+
.Build();
73+
6574
/// <summary>
6675
/// 获得/设置 颜色 默认 Color.None 无设置
6776
/// </summary>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the Apache 2.0 License
3+
// See the LICENSE file in the project root for more information.
4+
// Maintainer: Argo Zhang([email protected]) Website: https://www.blazor.zone
5+
6+
namespace BootstrapBlazor.Components;
7+
8+
/// <summary>
9+
/// ISelect 接口
10+
/// </summary>
11+
public interface ISelectGeneric<TValue>
12+
{
13+
/// <summary>
14+
/// 增加 SelectedItem 项方法
15+
/// </summary>
16+
/// <param name="item"></param>
17+
void Add(SelectedItem<TValue> item);
18+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
@namespace BootstrapBlazor.Components
2+
@using Microsoft.AspNetCore.Components.Web.Virtualization
3+
@typeparam TValue
4+
@inherits SelectBase<TValue>
5+
@attribute [JSModuleAutoLoader("./_content/BootstrapBlazor/Components/Select/Select.razor.js", JSObjectReference = true)]
6+
7+
@if (IsShowLabel)
8+
{
9+
<BootstrapLabel required="@Required" for="@InputId" ShowLabelTooltip="ShowLabelTooltip" Value="@DisplayText" />
10+
}
11+
<div @attributes="AdditionalAttributes" id="@Id" class="@ClassString">
12+
<CascadingValue Value="this" IsFixed="true">
13+
@Options
14+
</CascadingValue>
15+
<RenderTemplate>
16+
<div class="dropdown-toggle" data-bs-toggle="@ToggleString" data-bs-placement="@PlacementString" data-bs-offset="@OffsetString" data-bs-custom-class="@CustomClassString">
17+
@if (DisplayTemplate != null)
18+
{
19+
<div id="@InputId" class="@InputClassString" tabindex="0">
20+
@DisplayTemplate(SelectedRow)
21+
</div>
22+
}
23+
else
24+
{
25+
<input type="text" id="@InputId" disabled="@Disabled" placeholder="@PlaceHolder" class="@InputClassString" value="@SelectedRow.Text" @onchange="OnChange" readonly="@ReadonlyString" />
26+
}
27+
<span class="@AppendClassString"><i class="@DropdownIcon"></i></span>
28+
</div>
29+
@if (GetClearable())
30+
{
31+
<span class="@ClearClassString" @onclick="OnClearValue"><i class="@ClearIcon"></i></span>
32+
}
33+
<div class="dropdown-menu">
34+
@if (IsVirtualize)
35+
{
36+
@if (ShowSearch)
37+
{
38+
<div class="@SearchClassString">
39+
<input type="text" class="search-text form-control" autocomplete="off" value="@SearchText" @oninput="EventCallback.Factory.CreateBinder<string>(this, async v => await SearchTextChanged(v), SearchText)" aria-label="Search">
40+
<i class="@SearchIconString"></i>
41+
</div>
42+
}
43+
<div class="dropdown-virtual">
44+
@if (OnQueryAsync == null)
45+
{
46+
<Virtualize ItemSize="RowHeight" OverscanCount="OverscanCount" Items="@GetVirtualItems()" ChildContent="RenderRow" />
47+
}
48+
else
49+
{
50+
<Virtualize ItemSize="RowHeight" OverscanCount="OverscanCount" ItemsProvider="LoadItems" Placeholder="RenderPlaceHolderRow" ItemContent="RenderRow" @ref="VirtualizeElement" />
51+
}
52+
</div>
53+
}
54+
else
55+
{
56+
@if (ShowSearch)
57+
{
58+
<div class="@SearchClassString">
59+
<input type="text" class="search-text form-control" autocomplete="off" value="@SearchText" @oninput="EventCallback.Factory.CreateBinder<string>(this, async v => await SearchTextChanged(v), SearchText)" aria-label="Search">
60+
<i class="@SearchIconString"></i>
61+
</div>
62+
}
63+
@foreach (var itemGroup in Rows.GroupBy(i => i.GroupName))
64+
{
65+
if (!string.IsNullOrEmpty(itemGroup.Key))
66+
{
67+
if (GroupItemTemplate != null)
68+
{
69+
@GroupItemTemplate(itemGroup.Key)
70+
}
71+
else
72+
{
73+
<Divider Text="@itemGroup.Key" />
74+
}
75+
}
76+
@foreach (var item in itemGroup)
77+
{
78+
@RenderRow(item)
79+
}
80+
}
81+
@if (Rows.Count == 0)
82+
{
83+
<div class="dropdown-item">@NoSearchDataText</div>
84+
}
85+
}
86+
</div>
87+
@if (!IsPopover)
88+
{
89+
<div class="dropdown-menu-arrow"></div>
90+
}
91+
</RenderTemplate>
92+
</div>
93+
94+
@code {
95+
RenderFragment<SelectedItem<TValue>> RenderRow => item =>
96+
@<div class="@ActiveItem(item)" @onclick="() => OnClickItem(item)">
97+
@if (ItemTemplate != null)
98+
{
99+
@ItemTemplate(item)
100+
}
101+
else if (IsMarkupString)
102+
{
103+
@((MarkupString)item.Text)
104+
}
105+
else
106+
{
107+
@item.Text
108+
}
109+
</div>;
110+
111+
RenderFragment<PlaceholderContext> RenderPlaceHolderRow => context =>
112+
@<div class="dropdown-item">
113+
<div class="is-ph"></div>
114+
</div>;
115+
}

0 commit comments

Comments
 (0)