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
24 changes: 24 additions & 0 deletions src/BootstrapBlazor.Server/Components/Samples/EditorForms.razor
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,30 @@
</GroupBox>
</DemoBlock>

<DemoBlock Title="@Localizer["GroupTitle"]" Introduction="@Localizer["GroupIntro"]" Name="Group">
<section ignore>
<p>@((MarkupString)Localizer["GroupDescription"].Value)</p>
<BootstrapInputGroup>
<BootstrapInputGroupLabel DisplayText="GroupType"></BootstrapInputGroupLabel>
<Segmented @bind-Value="_groupType">
<SegmentedItem Text="GroupBox" Value="EditorFormGroupType.GroupBox" />
<SegmentedItem Text="RowHeader" Value="EditorFormGroupType.RowHeader" />
</Segmented>
</BootstrapInputGroup>
</section>
<EditorForm Model="@Model" GroupType="_groupType">
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing @ symbol before the variable reference. The GroupType parameter binding should be GroupType="@_groupType" instead of GroupType="_groupType". Without the @ symbol, the component will receive the literal string "_groupType" rather than the value of the variable.

Suggested change
<EditorForm Model="@Model" GroupType="_groupType">
<EditorForm Model="@Model" GroupType="@_groupType">

Copilot uses AI. Check for mistakes.
<FieldItems>
<EditorItem @bind-Field="@context.Name" GroupOrder="1" GroupName="Group 1"></EditorItem>
<EditorItem @bind-Field="@context.Address" GroupOrder="1" GroupName="Group 1"></EditorItem>
<EditorItem @bind-Field="@context.DateTime" GroupOrder="2" GroupName="Group 1"></EditorItem>
<EditorItem @bind-Field="@context.Count" GroupOrder="2" GroupName="Group 1"></EditorItem>
<EditorItem @bind-Field="@context.Education" GroupOrder="3" GroupName="Group 2"></EditorItem>
<EditorItem @bind-Field="@context.Complete" GroupOrder="3" GroupName="Group 2"></EditorItem>
<EditorItem @bind-Field="@context.Hobby" Items="@Hobbies" GroupOrder="4" GroupName="Group 3"></EditorItem>
</FieldItems>
</EditorForm>
</DemoBlock>

<AttributeTable Type="typeof(EditorForm<>)" />

<AttributeTable Type="typeof(EditorItem<,>)"></AttributeTable>
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public sealed partial class EditorForms
private IStringLocalizer<Foo>? FooLocalizer { get; set; }

private List<string> _ignoreItems = [];
private EditorFormGroupType _groupType = EditorFormGroupType.GroupBox;
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Field '_groupType' can be 'readonly'.

Suggested change
private EditorFormGroupType _groupType = EditorFormGroupType.GroupBox;
private readonly EditorFormGroupType _groupType = EditorFormGroupType.GroupBox;

Copilot uses AI. Check for mistakes.

private Task OnSwitchIgnoreItems()
{
Expand Down
3 changes: 3 additions & 0 deletions src/BootstrapBlazor.Server/Locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -2129,6 +2129,9 @@
"EditorFormTips3": "Complex edit columns, set up <code>EditTemplate</code> templates, and edit custom components",
"EditorFormTips4": "The buttons in the form can be set up multiplely, just set the buttons <code>Buttons</code> template",
"GroupBoxTitle": "An example of a form",
"GroupDescription": "Grouping is enabled by setting the <code>GroupName</code> parameter of the <code>EditorItem</code> component, and the order is controlled by <code>GroupOrder</code>.",
"GroupIntro": "The grouping format can be controlled by setting the <code>groupType</code> value.",
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent casing for parameter name. The text uses "groupType" (lowercase 'g') but should be "GroupType" (uppercase 'G') to match the parameter name. Other parameter references in the localization files use proper casing (e.g., "RowType" at line 3733).

Suggested change
"GroupIntro": "The grouping format can be controlled by setting the <code>groupType</code> value.",
"GroupIntro": "The grouping format can be controlled by setting the <code>GroupType</code> value.",

Copilot uses AI. Check for mistakes.
"GroupTitle": "Group",
"IgnoreItemsDescription": "This attribute has the same priority as the <code>Ignore</code> parameter in <code>EditorItem</code>. If it is set to ignore anywhere, it will not be rendered.",
"IgnoreItemsIntro": "By setting the <code>IgnoreItems</code> value, you can notify the component not to render the specified column in the collection.",
"IgnoreItemsSwitchButtonText": "Switch",
Expand Down
3 changes: 3 additions & 0 deletions src/BootstrapBlazor.Server/Locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2129,6 +2129,9 @@
"EditorFormTips3": "复杂编辑列,设置 <code>EditTemplate</code> 模板,进行自定义组件进行编辑",
"EditorFormTips4": "表单内按钮可以设置多个,设置 <code>Buttons</code> 模板即可",
"GroupBoxTitle": "表单示例",
"GroupDescription": "通过设置 <code>EditorItem</code> 组件参数 <code>GroupName</code> 开启分组功能,通过 <code>GroupOrder</code> 控制顺序 ",
"GroupIntro": "通过设置 <code>GroupType</code> 值控制分组形式",
"GroupTitle": "分组功能",
"IgnoreItemsDescription": "此属性的优先级与 <code>EditorItem</code> 参数 <code>Ignore</code> 相同,任何一个地方设置了忽略,最终都不会渲染",
"IgnoreItemsIntro": "通过设置 <code>IgnoreItems</code> 值通知组件不渲染集合中的指定列",
"IgnoreItemsSwitchButtonText": "切换",
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>10.3.1-beta02</Version>
<Version>10.3.1-beta03</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
8 changes: 8 additions & 0 deletions src/BootstrapBlazor/Components/EditorForm/EditorForm.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace BootstrapBlazor.Components;
public partial class EditorForm<TModel> : IShowLabel, IDisposable
{
private string? ClassString => CssBuilder.Default("bb-editor")
.AddClass("bb-editor-group-row-header", GroupType == EditorFormGroupType.RowHeader)
.AddClassFromAttributes(AdditionalAttributes)
.Build();

Expand Down Expand Up @@ -192,6 +193,13 @@ public partial class EditorForm<TModel> : IShowLabel, IDisposable
[Parameter]
public bool IsRenderWhenValueChanged { get; set; }

/// <summary>
/// <para lang="zh">获得/设置 分组类型 默认 <see cref="EditorFormGroupType.GroupBox"/></para>
/// <para lang="en">Gets or sets group type. Default is <see cref="EditorFormGroupType.GroupBox"/></para>
/// </summary>
[Parameter]
public EditorFormGroupType GroupType { get; set; }

/// <summary>
/// <para lang="zh">获得/设置 级联上下文 EditContext 实例 内置于 EditForm 或者 ValidateForm 时有值</para>
/// <para lang="en">Gets or sets Cascading EditContext Instance. Available when inside EditForm or ValidateForm</para>
Expand Down
41 changes: 40 additions & 1 deletion src/BootstrapBlazor/Components/EditorForm/EditorForm.razor.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.bb-editor {
.bb-editor {
position: relative;

.ef-loading {
Expand All @@ -9,4 +9,43 @@
bottom: 0;
background-color: var(--bs-body-bg);
}

&.bb-editor-group-row-header {
.groupbox {
--bb-groupbox-padding: 0;
--bb-groupbox-legend-top: 0;
--bb-groupbox-legend-left: 0;
--bb-groupbox-divider-color: var(--bs-border-color);
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
border: 0;

.legend {
writing-mode: vertical-rl;
text-orientation: mixed;
position: relative;
color: var(--bb-groupbox-divider-color);
}

.row {
margin-inline-start: 1rem;
flex: 1;
width: 1%;
min-width: 0;
position: relative;

&::before {
content: "";
width: 1px;
background-color: var(--bb-groupbox-divider-color);
position: absolute;
top: 1rem;
bottom: 0;
left: -0.5rem;
}
}
}
}
}
4 changes: 2 additions & 2 deletions src/BootstrapBlazor/Components/GroupBox/GroupBox.razor
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@namespace BootstrapBlazor.Components
@namespace BootstrapBlazor.Components
@inherits BootstrapComponentBase

<div @attributes="@AdditionalAttributes" class="@ClassString">
<label class="legend">@Title</label>
<span class="legend">@Title</span>
@ChildContent
</div>
25 changes: 25 additions & 0 deletions src/BootstrapBlazor/Enums/EditorFormGroupType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License
// See the LICENSE file in the project root for more information.
// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone

namespace BootstrapBlazor.Components;

/// <summary>
/// <para lang="zh">EditorForm 分组类型</para>
/// <para lang="en">EditorForm group type</para>
/// </summary>
public enum EditorFormGroupType
{
/// <summary>
/// <para lang="zh">使用 GroupBox 形式</para>
/// <para lang="en">Group box</para>
/// </summary>
GroupBox,

/// <summary>
/// <para lang="zh">使用 RowHeader 形式</para>
/// <para lang="en">Row header</para>
/// </summary>
RowHeader,
}
19 changes: 19 additions & 0 deletions test/UnitTest/Components/EditorFormTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,25 @@ public void Buttons_Ok()
});
}

[Fact]
public void GroupType_Ok()
{
var foo = new Foo();
var cut = Context.Render<EditorForm<Foo>>(pb =>
{
pb.Add(a => a.Model, foo);
pb.Add(a => a.GroupType, EditorFormGroupType.GroupBox);
});

cut.DoesNotContain("bb-editor-group-row-header");
Comment on lines +181 to +190
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Add a test to verify the default GroupType behavior when the parameter is not set.

This test only validates explicit GroupType values and never asserts the default. Please add a separate test that renders EditorForm<Foo> without setting GroupType and verifies that the bb-editor-group-row-header CSS class is absent, so we also cover the documented default behavior and guard against regressions in the default/ClassString logic.


cut.Render(pb =>
{
pb.Add(a => a.GroupType, EditorFormGroupType.RowHeader);
});
cut.Contains("bb-editor-group-row-header");
}

[Fact]
public void Alignment_Right()
{
Expand Down
Loading