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
14 changes: 14 additions & 0 deletions src/BootstrapBlazor.Server/Components/Samples/CheckboxLists.razor
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,20 @@
</div>
</DemoBlock>

<DemoBlock Title="@Localizer["ItemTemplateTitle"]"
Introduction="@Localizer["ItemTemplateIntro"]"
Name="ItemTemplate">
<CheckboxList TValue="string" Items="@IconDemoValues">
<ItemTemplate>
@if (context is IconSelectedItem item)
{
<i class="@item.Icon"></i>
<span>@item.Text</span>
}
</ItemTemplate>
</CheckboxList>
</DemoBlock>

<DemoBlock Title="@Localizer["EnumTitle"]" Introduction="@Localizer["EnumIntro"]" Name="Enum">
<section ignore>@((MarkupString)Localizer["EnumTip"].Value)</section>
<div class="row g-3">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ protected override void OnInitialized()
new() { Text = Localizer["item4"], Value = Localizer["item4"] },
};

IconDemoValues = new List<IconSelectedItem>()
{
new() { Text = "Item1", Value = "1", Icon = "fa-solid fa-users" },
new() { Text = "Item2", Value = "2", Icon = "fa-solid fa-users-gear" }
};

Dummy = new Foo() { Name = Localizer["Foo"] };
Model = Foo.Generate(LocalizerFoo);
FooItems = Foo.GenerateHobbies(LocalizerFoo);
Expand Down Expand Up @@ -135,6 +141,9 @@ protected override async Task OnInitializedAsync()
new() { Text = "Item 4", Value = "4" },
};

[NotNull]
private IEnumerable<IconSelectedItem>? IconDemoValues { get; set; }

private Task OnSelectedChanged(IEnumerable<SelectedItem> items, string value)
{
NormalLogger.Log($"{Localizer["Header"]} {items.Count(i => i.Active)} {Localizer["Counter"]}:{value}");
Expand All @@ -157,6 +166,11 @@ private Task OnMaxSelectedCountExceed()
return ToastService.Information(Localizer["OnMaxSelectedCountExceedTitle"], Localizer["OnMaxSelectedCountExceedContent", 2]);
}

class IconSelectedItem : SelectedItem
{
public string? Icon { get; init; }
}

private AttributeItem[] GetAttributes() =>
[
new()
Expand Down
9 changes: 9 additions & 0 deletions src/BootstrapBlazor.Server/Components/Samples/Checkboxs.razor
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@
</div>
</DemoBlock>

<DemoBlock Title="@Localizer["ItemTemplateTitle"]"
Introduction="@Localizer["ItemTemplateIntro"]"
Name="ItemTemplate">
<Checkbox TValue="string" State="CheckboxState.Checked">
<i class="fa-solid fa-flag"></i>
<span>@Localizer["StatusText1"]</span>
</Checkbox>
</DemoBlock>

<DemoBlock Title="@Localizer["DisplayTextTitle"]" Introduction="@Localizer["DisplayTextIntro"]" Name="DisplayText">
<div class="row g-3 form-inline">
<div class="col-12 col-md-3">
Expand Down
6 changes: 2 additions & 4 deletions src/BootstrapBlazor.Server/Components/Samples/Radios.razor
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,8 @@
<ItemTemplate>
@if (context is IconSelectedItem item)
{
<div>
<i class="@item.Icon"></i>
<span>@item.Text</span>
</div>
<i class="@item.Icon"></i>
<span>@item.Text</span>
}
</ItemTemplate>
</RadioList>
Expand Down
4 changes: 4 additions & 0 deletions src/BootstrapBlazor.Server/Locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -2369,6 +2369,8 @@
"ValidateFormTitle": "Used in forms",
"ValidateFormIntro": "When you use <code>Checkbox</code> in a form, the display label text is placed in front of the component",
"ValidateFormDescription": "The pre-label explicit rules are consistent with the <code>BootstrapInput</code> component <a href='input'>[portal]</a>",
"RadiosItemTemplateTitle": "ItemTemplate",
"RadiosItemTemplateIntro": "Set <code>ItemTemplate</code> for customer the item UI",
"OnBeforeStateChangedTitle": "OnBeforeStateChanged",
"OnBeforeStateChangedIntro": "By setting the <code>OnBeforeStateChanged</code> callback method, you can cancel the state change logic",
"OnBeforeStateChangedText": "Confirm",
Expand Down Expand Up @@ -2405,6 +2407,8 @@
"ShowLabelTitle": "Bidirectional binding collection",
"ShowLabelIntro": "Binding values are collections",
"ShowLabelTip": "<code>TValue</code> is set to <code>IEnumerable&lt;int&gt;</code> generic collection, the <Code>ValueField</Code> specified field of the bound collection must be consistent with the generic type",
"ItemTemplateTitle": "ItemTemplate",
"ItemTemplateIntro": "Set <code>ItemTemplate</code> for customer the item UI",
"EnumTitle": "Bidirectional binding enumeration",
"EnumIntro": "The binding value is enumeration",
"EnumTip": "When <code>CheckboxList</code> binds an enumeration set, <code>Items</code> does not need to be specified, <code>Items</code> will be automatically set to all values in the enumeration. If you need to bind some values, please provide the enumeration set <code>Items</code>",
Expand Down
12 changes: 8 additions & 4 deletions src/BootstrapBlazor.Server/Locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2369,6 +2369,8 @@
"ValidateFormTitle": "表单中使用",
"ValidateFormIntro": "在表单中使用 <code>Checkbox</code> 时,显示标签文字会放置到组件前面",
"ValidateFormDescription": "前置标签显式规则与 <code>BootstrapInput</code> 组件一致 <a href='input'>[传送门]</a>",
"ItemTemplateTitle": "项目模板",
"ItemTemplateIntro": "通过设置 <code>ItemTemplate</code> 自定义显示 UI",
"OnBeforeStateChangedTitle": "选中前回调方法",
"OnBeforeStateChangedIntro": "通过设置 <code>OnBeforeStateChanged</code> 回调方法,可取消选中逻辑",
"OnBeforeStateChangedText": "弹窗确认",
Expand Down Expand Up @@ -2405,6 +2407,8 @@
"ShowLabelTitle": "双向绑定集合",
"ShowLabelIntro": "绑定值为集合",
"ShowLabelTip": "<code>TValue</code> 设置为 <code>IEnumerable&lt;int&gt;</code> 泛型集合,绑定集合的 <code>ValueField</code> 指定字段必须与泛型类型一致",
"ItemTemplateTitle": "项目模板",
"ItemTemplateIntro": "通过设置 <code>ItemTemplate</code> 自定义显示 UI",
"EnumTitle": "双向绑定枚举",
"EnumIntro": "绑定值为枚举",
"EnumTip": "当 <code>CheckboxList</code> 绑定一个枚举集合时,<code>Items</code> 不需要指定,<code>Items</code> 会被自动设置成枚举里面所有的值,如果需要绑定部分值时,请自行提供枚举集合 <code>Items</code>",
Expand Down Expand Up @@ -3018,14 +3022,14 @@
"RadiosVerticalIntro": "通过设置 <code>IsVertical</code> 使组件内部竖向排列",
"RadiosEnumTitle": "绑定枚举类型",
"RadiosEnumIntro": "通过双向绑定 <code>Value</code> 无需设置 <code>Items</code>",
"RadiosIsButtonTitle": "按钮样式",
"RadiosIsButtonIntro": "通过设定 <code>IsButton</code> 值为 <code>True</code> 将候选项更改为按钮样式",
"RadiosItemTemplateTitle": "项目模板",
"RadiosItemTemplateIntro": "通过设置 <code>ItemTemplate</code> 自定义显示 UI",
"RadiosEnumDescription": "通过设置 <code>IsAutoAddNullItem</code> 自动添加 <b>空值</b> 选项,通过设置 <code>NullItemText</code> 自定义 <b>空值</b> 选项",
"RadiosEnumText": "空值",
"RadiosColorTitle": "颜色",
"RadiosColorIntro": "通过设置 <code>Color</code> 属性改变组件背景色",
"RadiosIsButtonTitle": "按钮样式",
"RadiosIsButtonIntro": "通过设定 <code>IsButton</code> 值为 <code>True</code> 将候选项更改为按钮样式",
"RadiosItemTemplateTitle": "项目模板",
"RadiosItemTemplateIntro": "通过设置 <code>ItemTemplate</code> 自定义显示 UI",
"RadiosDisplayText": "显示文字",
"RadiosNullItemText": "空值显示文字",
"RadiosIsDisabled": "是否禁用",
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.3.1-beta01</Version>
<Version>9.3.1-beta02</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
8 changes: 7 additions & 1 deletion src/BootstrapBlazor/Components/Checkbox/Checkbox.razor
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@
<div @attributes="AdditionalAttributes" class="@ClassString">
<input type="checkbox" id="@Id" class="@InputClassString" disabled="@Disabled" checked="@CheckedString"
@onclick="OnToggleClick" @onclick:stopPropagation="StopPropagation" @onclick:preventDefault="false" />
@if (IsShowAfterLabel)
@if(ChildContent != null)
{
<label class="form-check-label" for="@Id">
@ChildContent
</label>
}
else if (IsShowAfterLabel)
{
<label class="form-check-label" for="@Id">
@if (ShowLabelTooltip is true)
Expand Down
6 changes: 6 additions & 0 deletions src/BootstrapBlazor/Components/Checkbox/Checkbox.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ public partial class Checkbox<TValue> : ValidateBase<TValue>
[Parameter]
public bool StopPropagation { get; set; }

/// <summary>
/// 获得/设置 子组件 RenderFragment 实例
/// </summary>
[Parameter]
public RenderFragment? ChildContent { get; set; }

/// <summary>
/// <inheritdoc/>
/// </summary>
Expand Down
5 changes: 3 additions & 2 deletions src/BootstrapBlazor/Components/Checkbox/CheckboxList.razor
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ else
<div @key="item" class="@CheckboxItemClassString">
<Checkbox TValue="bool" IsDisabled="GetDisabledState(item)"
ShowAfterLabel="true" ShowLabel="false" ShowLabelTooltip="ShowLabelTooltip"
DisplayText="@item.Text" OnBeforeStateChanged="_onBeforeStateChangedCallback!"
Value="@item.Active" OnStateChanged="@((state, v) => OnStateChanged(item, v))"></Checkbox>
DisplayText="@item.Text" OnBeforeStateChanged="_onBeforeStateChangedCallback"
Value="@item.Active" OnStateChanged="@((state, v) => OnStateChanged(item, v))"
ChildContent="GetChildContent(item)"></Checkbox>
</div>
}
</div>
Expand Down
10 changes: 10 additions & 0 deletions src/BootstrapBlazor/Components/Checkbox/CheckboxList.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ public partial class CheckboxList<TValue> : ValidateBase<TValue>
[Parameter]
public Func<Task>? OnMaxSelectedCountExceed { get; set; }

/// <summary>
/// 获得/设置 项模板
/// </summary>
[Parameter]
public RenderFragment<SelectedItem>? ItemTemplate { get; set; }

/// <summary>
/// 获得 当前选项是否被禁用
/// </summary>
Expand Down Expand Up @@ -295,4 +301,8 @@ protected virtual void EnsureParameterValid()
throw new NotSupportedException();
}
}

private RenderFragment? GetChildContent(SelectedItem item) => ItemTemplate == null
? null
: ItemTemplate(item);
}
8 changes: 0 additions & 8 deletions src/BootstrapBlazor/Components/Radio/Radio.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,11 @@ public partial class Radio<TValue> : Checkbox<TValue>
[Parameter]
public Func<TValue, Task>? OnClick { get; set; }

/// <summary>
/// 获得/设置 子组件 RenderFragment 实例
/// </summary>
[Parameter]
public RenderFragment? ChildContent { get; set; }

/// <summary>
/// 获得/设置 Radio 组名称一般来讲需要设置 默认为 null 未设置
/// </summary>
[Parameter]
#if NET6_0_OR_GREATER
[EditorRequired]
#endif
public string? GroupName { get; set; }

private string? ClassString => CssBuilder.Default("form-check")
Expand Down
3 changes: 1 addition & 2 deletions src/BootstrapBlazor/Components/Radio/RadioList.razor
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ else
<div @attributes="@AdditionalAttributes" class="@ClassString" role="group">
@foreach (var item in Items)
{
var content = GetChildContent(item);
<Radio TValue="SelectedItem" Value="@item" Color="@Color" GroupName="@GroupName" IsDisabled="@GetDisabledState(item)" ShowAfterLabel="true" ShowLabel="false" DisplayText="@item.Text" State="@CheckState(item)" OnClick="OnClick" ChildContent="content!"></Radio>
<Radio TValue="SelectedItem" Value="@item" Color="@Color" GroupName="@GroupName" IsDisabled="@GetDisabledState(item)" ShowAfterLabel="true" ShowLabel="false" DisplayText="@item.Text" State="@CheckState(item)" OnClick="OnClick" ChildContent="GetChildContent(item)"></Radio>
}
</div>
}
6 changes: 0 additions & 6 deletions src/BootstrapBlazor/Components/Radio/RadioList.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,6 @@ public partial class RadioList<TValue>
[NotNull]
public string? NullItemText { get; set; }

/// <summary>
/// 获得/设置 项模板
/// </summary>
[Parameter]
public RenderFragment<SelectedItem>? ItemTemplate { get; set; }

/// <summary>
/// 获得/设置 未设置选中项时是否自动选择第一项 默认 true
/// </summary>
Expand Down
30 changes: 30 additions & 0 deletions test/UnitTest/Components/CheckboxListTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ public void Checkbox_Ok()
Assert.DoesNotContain("is-label", cut.Markup);
}

[Fact]
public void ChildContent_Ok()
{
var cut = Context.RenderComponent<Checkbox<string>>(builder =>
{
builder.Add(a => a.ChildContent, pb => pb.AddContent(0, "test-childcontent"));
});
cut.MarkupMatches("<div class=\"form-check\"><input type=\"checkbox\" diff:ignore class=\"form-check-input\" blazor:onclick=\"1\" /><label class=\"form-check-label\" diff:ignore>test-childcontent</label></div>");
}

[Fact]
public void StopPropagation_Ok()
{
Expand Down Expand Up @@ -443,6 +453,26 @@ await cut.InvokeAsync(async () =>
Assert.False(max);
}

[Fact]
public void ItemTemplate_Ok()
{
var items = new List<SelectedItem>()
{
new("1", "Test 1"),
new("2", "Test 2"),
new("3", "Test 3")
};
var cut = Context.RenderComponent<CheckboxList<string>>(pb =>
{
pb.Add(a => a.Items, items);
pb.Add(a => a.ItemTemplate, item => b =>
{
b.AddContent(0, item.Text);
});
});
cut.MarkupMatches("<div diff:ignore class=\"checkbox-list form-control\" tabindex=\"0\" hidefocus=\"true\"><div class=\"checkbox-item\"><div class=\"form-check is-label\"><input type=\"checkbox\" diff:ignore class=\"form-check-input\" blazor:onclick=\"1\" /><label class=\"form-check-label\" diff:ignore>Test 1</label></div></div><div class=\"checkbox-item\"><div class=\"form-check is-label\"><input type=\"checkbox\" diff:ignore class=\"form-check-input\" blazor:onclick=\"2\" /><label class=\"form-check-label\" diff:ignore>Test 2</label></div></div><div class=\"checkbox-item\"><div class=\"form-check is-label\"><input type=\"checkbox\" diff:ignore class=\"form-check-input\" blazor:onclick=\"3\" /><label class=\"form-check-label\" diff:ignore>Test 3</label></div></div></div>");
}

private class CheckboxListGenericMock<T>
{

Expand Down
Loading