From b3df203b2edba2351b75aada6f3071bacc0969e4 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Thu, 12 Feb 2026 19:04:51 +0800 Subject: [PATCH 01/10] =?UTF-8?q?style:=20=E6=9B=B4=E6=96=B0=E5=BC=B9?= =?UTF-8?q?=E7=AA=97=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor/Components/Table/Table.razor.scss | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.scss b/src/BootstrapBlazor/Components/Table/Table.razor.scss index 7591f140041..e5ff775a1e0 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.scss +++ b/src/BootstrapBlazor/Components/Table/Table.razor.scss @@ -1,3 +1,7 @@ +.dropdown-menu-popover { + --bb-table-columnlist-max-height: var(--bb-dropdown-max-height); +} + .table-container { --bb-table-td-padding-x: .5rem; --bb-table-td-padding-y: .5rem; @@ -307,7 +311,8 @@ margin-block-end: .5rem; } -.table-toolbar .dropdown-column .dropdown-menu { +.table-toolbar .dropdown-column .dropdown-menu, +.dropdown-menu-popover { &:not(.dropdown-menu-controls) { max-height: var(--bb-table-columnlist-max-height); From 2e14d96585295ec94e1af0d3d824d8cc6a3964b9 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Thu, 12 Feb 2026 19:05:35 +0800 Subject: [PATCH 02/10] =?UTF-8?q?refactor:=20=E6=A0=BC=E5=BC=8F=E5=8C=96?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor/Components/Table/Table.razor.js | 8 +++----- src/BootstrapBlazor/wwwroot/modules/base-popover.js | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.js b/src/BootstrapBlazor/Components/Table/Table.razor.js index 5d9f7316d8e..f2b4e140286 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.js +++ b/src/BootstrapBlazor/Components/Table/Table.razor.js @@ -5,7 +5,7 @@ import Data from '../../modules/data.js' import EventHandler from '../../modules/event-handler.js' import Popover from "../../modules/base-popover.js" -export function init(id, invoke, options) { +export async function init(id, invoke, options) { const el = document.getElementById(id) if (el === null) { return @@ -18,7 +18,7 @@ export function init(id, invoke, options) { } Data.set(id, table) - reset(id) + await reset(id) } export function saveColumnList(tableName, columns) { @@ -121,7 +121,6 @@ export async function reset(id) { table.pages = [...table.el.children].find(i => i.classList.contains('nav-pages')); - setColumnToolboxListener(table); if (isVisible(table.el) === false) { @@ -824,8 +823,7 @@ const calcCellWidth = cell => { document.body.appendChild(div); const cellStyle = getComputedStyle(cell); - const width = div.offsetWidth + parseFloat(cellStyle.getPropertyValue('padding-left')) + parseFloat(cellStyle.getPropertyValue('padding-right')) + parseFloat(cellStyle.getPropertyValue('border-left-width')) + parseFloat(cellStyle.getPropertyValue('border-right-width')) + 1; - return width; + return div.offsetWidth + parseFloat(cellStyle.getPropertyValue('padding-left')) + parseFloat(cellStyle.getPropertyValue('padding-right')) + parseFloat(cellStyle.getPropertyValue('border-left-width')) + parseFloat(cellStyle.getPropertyValue('border-right-width')) + 1; } const closeAllTips = (columns, self) => { diff --git a/src/BootstrapBlazor/wwwroot/modules/base-popover.js b/src/BootstrapBlazor/wwwroot/modules/base-popover.js index ad08a187f43..9cc67029f7f 100644 --- a/src/BootstrapBlazor/wwwroot/modules/base-popover.js +++ b/src/BootstrapBlazor/wwwroot/modules/base-popover.js @@ -74,7 +74,7 @@ const Popover = { popover.triggerHideCallback = () => { if (popover.hideCallback) { popover.hideCallback(); - }; + } } if (popover.isPopover) { From e8426a363dd870b7bdebd09526140a5adb418550 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Thu, 12 Feb 2026 19:06:13 +0800 Subject: [PATCH 03/10] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20resetColumnL?= =?UTF-8?q?ist=20=E5=9B=9E=E8=B0=83=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Table/Table.razor.cs | 11 ++++++++ .../Components/Table/Table.razor.js | 28 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.cs b/src/BootstrapBlazor/Components/Table/Table.razor.cs index 61b2722903a..752dab34312 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.cs @@ -941,8 +941,11 @@ public async Task ExpandDetailRow(TItem item) private string? DropdownListClassString => CssBuilder.Default("dropdown-menu dropdown-menu-end shadow") .AddClass("dropdown-menu-controls", ShowColumnListControls) + .AddClass("dropdown-menu-popover", IsPopoverToolbarDropdownButton) .Build(); + private bool _lastIsPopoverToolbarDropdownButtonValue = false; + /// /// /// @@ -1151,6 +1154,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) if (firstRender) { + _lastIsPopoverToolbarDropdownButtonValue = IsPopoverToolbarDropdownButton; await ProcessFirstRender(); } @@ -1208,6 +1212,13 @@ protected override async Task OnAfterRenderAsync(bool firstRender) await InvokeVoidAsync("scrollTo", Id); } + // 如果 ColumnList 显示状态改变重置 ColumnList 渲染模式 + if(_lastIsPopoverToolbarDropdownButtonValue != IsPopoverToolbarDropdownButton) + { + _lastIsPopoverToolbarDropdownButtonValue = IsPopoverToolbarDropdownButton; + await InvokeVoidAsync("resetColumnList", Id); + } + // 增加去重保护 _loop 为 false 时执行 if (!_loop && IsAutoRefresh && AutoRefreshInterval > 500) { diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.js b/src/BootstrapBlazor/Components/Table/Table.razor.js index f2b4e140286..735416659bf 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.js +++ b/src/BootstrapBlazor/Components/Table/Table.razor.js @@ -1001,6 +1001,34 @@ const setToolbarDropdown = (table, toolbar) => { }) } +export function resetColumnList(id) { + const table = Data.get(id); + if (table) { + const { toolbar } = table; + if (toolbar) { + console.log(table); + const dropdown = toolbar.querySelector('.dropdown-column'); + console.log(dropdown); + + if (dropdown) { + const button = dropdown.querySelector('.dropdown-toggle') + if (button.getAttribute('data-bs-toggle') === 'bb.dropdown') { + table.popovers.push(Popover.init(dropdown, { + isDisabled: () => false + })); + } + else { + const p = table.popovers.find(i => i.el === dropdown); + if (p) { + Popover.dispose(p); + table.popovers = table.popovers.filter(i => i !== p); + } + } + } + } + } +} + const saveColumnWidth = table => { const cols = table.columns const tableWidth = table.tables[0].offsetWidth From e30da71246bec21ef224364e867c87e8b4083191 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Thu, 12 Feb 2026 19:06:24 +0800 Subject: [PATCH 04/10] =?UTF-8?q?doc:=20=E6=9B=B4=E6=96=B0=E7=A4=BA?= =?UTF-8?q?=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor.Server/Locales/en-US.json | 1 + src/BootstrapBlazor.Server/Locales/zh-CN.json | 1 + 2 files changed, 2 insertions(+) diff --git a/src/BootstrapBlazor.Server/Locales/en-US.json b/src/BootstrapBlazor.Server/Locales/en-US.json index f8b9deb9d07..dbcc3bdc275 100644 --- a/src/BootstrapBlazor.Server/Locales/en-US.json +++ b/src/BootstrapBlazor.Server/Locales/en-US.json @@ -4559,6 +4559,7 @@ "ShownWithBreakPointP4": "Because the Table component supports mobile adaptation by default, the card mode is used for small screens. In this example, the explicit setting uses RenderMode=\"TableRenderMode. Table\" mode", "ShownWithBreakPointTitle": "Automatically show/hide columns based on screen width", "TablesColumnDescription": "Used to display multiple pieces of data with similar structures, data can be sorted, filtered, compared or other custom operations.", + "IsPopoverToolbarDropdownButtonDesc": "The IsPopoverToolbarDropdownButton parameter controls whether the column list is displayed as a popover or a dropdown menu. The default value is false, which means it is displayed as a dropdown menu. When set to true, it is displayed as a popover.", "TablesColumnTitle": "Table Column", "VisibleIntro": "Set whether the column is displayed by specifying the ShowColumnList attribute", "VisibleP1": "ShowColumnList The default value is false, and if it is explicitly specified as true, the corresponding column adjustment button will appear in the toolbar", diff --git a/src/BootstrapBlazor.Server/Locales/zh-CN.json b/src/BootstrapBlazor.Server/Locales/zh-CN.json index 1bdd5814fe5..21afc4cc7fd 100644 --- a/src/BootstrapBlazor.Server/Locales/zh-CN.json +++ b/src/BootstrapBlazor.Server/Locales/zh-CN.json @@ -4559,6 +4559,7 @@ "ShownWithBreakPointP4": "由于 Table 组件默认是支持移动端适配,所以小屏幕时采用的是卡片式模式,本例中显式设置使用 RenderMode=\"TableRenderMode.Table\" 模式", "ShownWithBreakPointTitle": "根据屏幕宽度自动显示/隐藏列", "TablesColumnDescription": "用于展示多条结构类似的数据,可对数据进行排序、筛选、对比或其他自定义操作。", + "IsPopoverToolbarDropdownButtonDesc": "通过设置 IsPopoverToolbarDropdownButton 属性,工具栏列下拉框显示为气泡弹窗形式", "TablesColumnTitle": "Table 表格", "VisibleIntro": "通过指定 ShowColumnList 属性设置列是否显示", "VisibleP1": "ShowColumnList 默认值为 false,显式指定为 true 后工具栏出现相应列调整按钮", From 764620ddb8e8675ccfe67c1ca32528dcd7fe4fe5 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Thu, 12 Feb 2026 19:06:41 +0800 Subject: [PATCH 05/10] =?UTF-8?q?doc:=20=E5=A2=9E=E5=8A=A0=E5=8F=98?= =?UTF-8?q?=E9=87=8F=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Samples/Table/TablesColumnList.razor | 23 +++++++++++++++++-- .../Samples/Table/TablesColumnList.razor.cs | 3 +++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumnList.razor b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumnList.razor index ec2a6072130..4a07405604e 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumnList.razor +++ b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumnList.razor @@ -18,14 +18,33 @@

@((MarkupString)Localizer["VisibleP3"].Value)

@((MarkupString)Localizer["VisibleP4"].Value)

@((MarkupString)Localizer["ResetVisibleColumnsDesc"].Value)

+

@((MarkupString)Localizer["IsPopoverToolbarDropdownButtonDesc"].Value)

+
+
+ + + + + +
+
+ + + + + +
+
diff --git a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumnList.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumnList.razor.cs index ffe6e3be8ed..ba631b77f6d 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumnList.razor.cs +++ b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumnList.razor.cs @@ -27,6 +27,9 @@ public partial class TablesColumnList [NotNull] private Table? TableColumnVisible { get; set; } + private bool _isPopoverToolbarDropdownButton = true; + private bool _showColumnListControls = true; + /// /// OnInitialized 方法 /// From d5a06160251f9a0241c4c9a1c4fc8c5fe0efff06 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Thu, 12 Feb 2026 19:34:02 +0800 Subject: [PATCH 06/10] =?UTF-8?q?refactor:=20=E6=9B=B4=E6=96=B0=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E7=BC=96=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor/wwwroot/modules/base-popover.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BootstrapBlazor/wwwroot/modules/base-popover.js b/src/BootstrapBlazor/wwwroot/modules/base-popover.js index 9cc67029f7f..61d47ebb8e8 100644 --- a/src/BootstrapBlazor/wwwroot/modules/base-popover.js +++ b/src/BootstrapBlazor/wwwroot/modules/base-popover.js @@ -1,4 +1,4 @@ -import { getDescribedElement, getDescribedOwner, hackTooltip, hackPopover, isDisabled, registerBootstrapBlazorModule } from "./utility.js" +import { getDescribedElement, getDescribedOwner, hackTooltip, hackPopover, isDisabled, registerBootstrapBlazorModule } from "./utility.js" import EventHandler from "./event-handler.js" const Popover = { From 6f2884890a8b41e1898810d4769ae3d2376a952e Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Thu, 12 Feb 2026 19:34:15 +0800 Subject: [PATCH 07/10] =?UTF-8?q?refactor:=20=E6=9B=B4=E6=96=B0=E9=94=80?= =?UTF-8?q?=E6=AF=81=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Table/Table.razor.js | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.js b/src/BootstrapBlazor/Components/Table/Table.razor.js index 735416659bf..5066ea5f35a 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.js +++ b/src/BootstrapBlazor/Components/Table/Table.razor.js @@ -1,6 +1,6 @@ export { getResponsive } from '../../modules/responsive.js' import { copy, drag, getDescribedElement, getOuterHeight, getWidth, isVisible } from '../../modules/utility.js' -import browser from '../../modules/browser.min.mjs' +import browser from '../../modules/browser.min.mjs' import Data from '../../modules/data.js' import EventHandler from '../../modules/event-handler.js' import Popover from "../../modules/base-popover.js" @@ -1006,24 +1006,23 @@ export function resetColumnList(id) { if (table) { const { toolbar } = table; if (toolbar) { - console.log(table); const dropdown = toolbar.querySelector('.dropdown-column'); - console.log(dropdown); - if (dropdown) { - const button = dropdown.querySelector('.dropdown-toggle') + const button = dropdown.querySelector('.dropdown-toggle'); + const dropdownToggle = bootstrap.Dropdown.getInstance(button); + if (dropdownToggle) { + dropdownToggle.dispose(); + } + const p = table.popovers.find(i => i.el === dropdown); + if (p) { + table.popovers = table.popovers.filter(i => i !== p); + Popover.dispose(p); + } if (button.getAttribute('data-bs-toggle') === 'bb.dropdown') { table.popovers.push(Popover.init(dropdown, { isDisabled: () => false })); } - else { - const p = table.popovers.find(i => i.el === dropdown); - if (p) { - Popover.dispose(p); - table.popovers = table.popovers.filter(i => i !== p); - } - } } } } From 2861638cfb63e689eec954853a9dd34bc2ed67a5 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 13 Feb 2026 09:16:38 +0800 Subject: [PATCH 08/10] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/UnitTest/Components/TableTest.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/UnitTest/Components/TableTest.cs b/test/UnitTest/Components/TableTest.cs index 602cc7aff1d..8fc51946753 100644 --- a/test/UnitTest/Components/TableTest.cs +++ b/test/UnitTest/Components/TableTest.cs @@ -747,7 +747,7 @@ public async Task ShowColumnList_Ok() pb.Add(a => a.RenderMode, TableRenderMode.Table); pb.Add(a => a.ShowToolbar, true); pb.Add(a => a.ShowColumnList, true); - pb.Add(a => a.IsPopoverToolbarDropdownButton, true); + pb.Add(a => a.IsPopoverToolbarDropdownButton, false); pb.Add(a => a.AllowResizing, true); pb.Add(a => a.ShowColumnWidthTooltip, true); pb.Add(a => a.ColumnWidthTooltipPrefix, "test"); @@ -775,6 +775,7 @@ public async Task ShowColumnList_Ok() }); }); cut.Contains("Test_Column_List"); + cut.DoesNotContain("dropdown-menu-popover"); var item = cut.FindComponents>()[0]; await cut.InvokeAsync(item.Instance.OnToggleClick); @@ -782,6 +783,13 @@ public async Task ShowColumnList_Ok() await cut.InvokeAsync(item.Instance.OnToggleClick); Assert.False(show); + + var table = cut.FindComponent>(); + table.Render(pb => + { + pb.Add(a => a.IsPopoverToolbarDropdownButton, true); + }); + table.Contains("dropdown-menu-popover"); } [Fact] From 8910f06f178fe142d5dd12afe3dda1c5d9ea41a0 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 13 Feb 2026 09:17:52 +0800 Subject: [PATCH 09/10] =?UTF-8?q?refactor:=20=E4=BB=A3=E7=A0=81=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor/Components/Table/Table.razor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.cs b/src/BootstrapBlazor/Components/Table/Table.razor.cs index 752dab34312..432c56e238a 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.cs @@ -1213,7 +1213,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) } // 如果 ColumnList 显示状态改变重置 ColumnList 渲染模式 - if(_lastIsPopoverToolbarDropdownButtonValue != IsPopoverToolbarDropdownButton) + if (_lastIsPopoverToolbarDropdownButtonValue != IsPopoverToolbarDropdownButton) { _lastIsPopoverToolbarDropdownButtonValue = IsPopoverToolbarDropdownButton; await InvokeVoidAsync("resetColumnList", Id); From f2b942767aed22a08e94ed40e5bb571b9bb272df Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 13 Feb 2026 09:23:14 +0800 Subject: [PATCH 10/10] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Samples/Table/TablesColumnList.razor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumnList.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumnList.razor.cs index ba631b77f6d..c8f56ba7888 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumnList.razor.cs +++ b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumnList.razor.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// 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 @@ -54,7 +54,7 @@ private Task> OnQueryAsync(QueryPageOptions options) IEnumerable items = Items; // 过滤 var isFiltered = false; - if (options.Filters.Any()) + if (options.Filters.Count > 0) { items = items.Where(options.Filters.GetFilterFunc()); isFiltered = true;