-
OnClickTabItem(item))" @onclick:preventDefault="@(!ClickTabToNavigation)">
+ OnContextMenu(e, item)" @oncontextmenu:preventDefault="IsPreventDefault"
+ @onclick="@(() => OnClickTabItem(item))" @onclick:preventDefault="@(!ClickTabToNavigation)">
@RenderHeaderItemContent(item)
@if (TabStyle == TabStyle.Chrome)
diff --git a/src/BootstrapBlazor/Components/Tab/Tab.razor.cs b/src/BootstrapBlazor/Components/Tab/Tab.razor.cs
index 84a50c17829..33aebffd200 100644
--- a/src/BootstrapBlazor/Components/Tab/Tab.razor.cs
+++ b/src/BootstrapBlazor/Components/Tab/Tab.razor.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
+using Microsoft.AspNetCore.Components.Web;
using Microsoft.Extensions.Localization;
using System.Collections.Concurrent;
using System.Reflection;
@@ -370,6 +371,9 @@ public partial class Tab : IHandlerException
[Inject, NotNull]
private DialogService? DialogService { get; set; }
+ [CascadingParameter]
+ private ContextMenuZone? ContextMenuZone { get; set; }
+
private ConcurrentDictionary
LazyTabCache { get; } = new();
private bool HandlerNavigation { get; set; }
@@ -382,6 +386,8 @@ public partial class Tab : IHandlerException
private readonly ConcurrentDictionary _cache = [];
+ private bool IsPreventDefault => ContextMenuZone != null;
+
///
///
///
@@ -965,4 +971,12 @@ protected override async ValueTask DisposeAsync(bool disposing)
ErrorLogger?.UnRegister(this);
}
}
+
+ private async Task OnContextMenu(MouseEventArgs e, TabItem item)
+ {
+ if (ContextMenuZone != null)
+ {
+ await ContextMenuZone.OnContextMenu(e, item);
+ }
+ }
}
diff --git a/test/UnitTest/Components/TabTest.cs b/test/UnitTest/Components/TabTest.cs
index 9f5152d4121..f32d7dbe880 100644
--- a/test/UnitTest/Components/TabTest.cs
+++ b/test/UnitTest/Components/TabTest.cs
@@ -7,6 +7,7 @@
using Bunit.TestDoubles;
using Microsoft.AspNetCore.Components.Rendering;
using System.Reflection;
+using System.Threading.Tasks;
using UnitTest.Misc;
namespace UnitTest.Components;
@@ -25,6 +26,49 @@ protected override void ConfigureServices(IServiceCollection services)
});
}
+ [Fact]
+ public async Task ContextMenu_Ok()
+ {
+ var clicked = false;
+ var cut = Context.RenderComponent(pb =>
+ {
+ pb.AddChildContent(pb =>
+ {
+ pb.AddChildContent(pb =>
+ {
+ pb.Add(a => a.Text, "Tab1");
+ pb.Add(a => a.Url, "/Index");
+ pb.Add(a => a.Closable, true);
+ pb.Add(a => a.Icon, "fa-solid fa-font-awesome");
+ pb.Add(a => a.ChildContent, "Tab1-Content");
+ });
+ });
+ pb.AddChildContent(pb =>
+ {
+ pb.AddChildContent(pb =>
+ {
+ pb.Add(a => a.Text, "test-close");
+ pb.Add(a => a.OnClick, (context, item) =>
+ {
+ clicked = true;
+ if (item is TabItem tabItem)
+ {
+
+ }
+ return Task.CompletedTask;
+ });
+ });
+ });
+ });
+
+ var menuItem = cut.Find(".tabs-item");
+ await cut.InvokeAsync(() => menuItem.ContextMenu());
+
+ var item = cut.Find(".dropdown-menu .dropdown-item");
+ await cut.InvokeAsync(() => item.Click());
+ Assert.True(clicked);
+ }
+
[Fact]
public void ToolbarTemplate_Ok()
{