diff --git a/src/BootstrapBlazor.Server/Components/Samples/Tabs.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/Tabs.razor.cs index 7b0eb2d6c35..fa194676236 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/Tabs.razor.cs +++ b/src/BootstrapBlazor.Server/Components/Samples/Tabs.razor.cs @@ -202,6 +202,14 @@ private AttributeItem[] GetAttributes() => DefaultValue = "false" }, new() + { + Name = nameof(Tab.IsLoopSwitchTabItem), + Description = Localizer["TabAttIsLoopSwitchTabItem"].Value, + Type = "boolean", + ValueList = "true/false", + DefaultValue = "true" + }, + new() { Name = "ShowClose", Description = Localizer["TabAtt4ShowClose"].Value, diff --git a/src/BootstrapBlazor.Server/Locales/en-US.json b/src/BootstrapBlazor.Server/Locales/en-US.json index 977aea12c61..b0a740221e1 100644 --- a/src/BootstrapBlazor.Server/Locales/en-US.json +++ b/src/BootstrapBlazor.Server/Locales/en-US.json @@ -2063,7 +2063,7 @@ "Block9Div": "Header", "TabsAppTitle": "Live Tab components", "TabsAppIntro": "By setting the ShowExtendButtons property to true, turning on the left and right buttons of the component and closing the drop-down menu, it is very useful in practice", - "TabsAppDescription": "Dynamically adjust the number of TabItem by adding, deletebuttons to view the left and right effects beyond the number of containers, user management is set to not close, and the feature button cannot close this tab", + "TabsAppDescription": "Dynamically adjust the number of TabItem by adding, deletebuttons to view the left and right effects beyond the number of containers, user management is set to not close, and the feature button cannot close this tab. The component switches tabs in a loop by default. You can disable this feature by IsLoopSwitchTabItem=\"false\"", "TabsIsOnlyRenderActiveTitle": "Only the current label is rendered", "TabsIsOnlyRenderActiveIntro": "By setting the isOnlyRenderActiveTab parameter, the component renders only the current active label", "BlockSetTextTitle": "TabItem Text", @@ -2090,6 +2090,7 @@ "TabAttShowNavigatorButtons": "Whether to display the previous and next navigation buttons", "TabAttShowActiveBar": "Whether to display active bar", "TabAttIsLazyLoadTabItem": "Whether lazy load tab item", + "TabAttIsLoopSwitchTabItem": "Whether loop switch tab item", "TabAtt6ClickTabToNavigation": "Whether to navigate when you click on the title", "TabAtt7Placement": "Set the label position", "TabAtt8Height": "Set the label height", diff --git a/src/BootstrapBlazor.Server/Locales/zh-CN.json b/src/BootstrapBlazor.Server/Locales/zh-CN.json index 71c8a1d4e93..2fc69848e37 100644 --- a/src/BootstrapBlazor.Server/Locales/zh-CN.json +++ b/src/BootstrapBlazor.Server/Locales/zh-CN.json @@ -2063,7 +2063,7 @@ "Block9Div": "网站 Header", "TabsAppTitle": "实战 Tab 组件", "TabsAppIntro": "通过设置 ShowExtendButtons 属性为 true,开启组件左右移动按钮与关闭下拉菜单,实战中非常实用", - "TabsAppDescription": "通过 添加 删除 按钮动态调整 TabItem 数量,使其超出容器数量查看,左右移动效果;用户管理 设置为不可关闭;功能按钮无法关闭这个标签页", + "TabsAppDescription": "通过 添加 删除 按钮动态调整 TabItem 数量,使其超出容器数量查看,左右移动效果;用户管理 设置为不可关闭;功能按钮无法关闭这个标签页。组件默认是循环切换标签页的,可以通过 IsLoopSwitchTabItem=\"false\" 关闭这个功能", "TabsIsOnlyRenderActiveTitle": "仅渲染当前标签", "TabsIsOnlyRenderActiveIntro": "通过设置 IsOnlyRenderActiveTab 参数使组件仅渲染当前活动标签", "BlockSetTextTitle": "设置标签文本", @@ -2090,6 +2090,7 @@ "TabAttShowNavigatorButtons": "是否显示前后导航按钮", "TabAttShowActiveBar": "是否显示活动标签", "TabAttIsLazyLoadTabItem": "是否延时加载标签内容", + "TabAttIsLoopSwitchTabItem": "是否循环切换标签", "TabAtt6ClickTabToNavigation": "点击标题时是否导航", "TabAtt7Placement": "设置标签位置", "TabAtt8Height": "设置标签高度", diff --git a/src/BootstrapBlazor/BootstrapBlazor.csproj b/src/BootstrapBlazor/BootstrapBlazor.csproj index 7f0af05488b..277f6ba5401 100644 --- a/src/BootstrapBlazor/BootstrapBlazor.csproj +++ b/src/BootstrapBlazor/BootstrapBlazor.csproj @@ -1,7 +1,7 @@  - 9.5.7 + 9.5.8-beta01 diff --git a/src/BootstrapBlazor/Components/Tab/Tab.razor.cs b/src/BootstrapBlazor/Components/Tab/Tab.razor.cs index 5f1f6c71128..b7ddb2237a3 100644 --- a/src/BootstrapBlazor/Components/Tab/Tab.razor.cs +++ b/src/BootstrapBlazor/Components/Tab/Tab.razor.cs @@ -139,6 +139,12 @@ public partial class Tab : IHandlerException [Parameter] public bool ShowNavigatorButtons { get; set; } = true; + /// + /// Gets or sets whether auto reset tab item index. Default is true. + /// + [Parameter] + public bool IsLoopSwitchTabItem { get; set; } = true; + /// /// 获得/设置 是否显示活动标签 默认为 true 显示 /// @@ -650,7 +656,14 @@ public void ClickPrevTab() index--; if (index < 0) { - index = TabItems.Count - 1; + if (IsLoopSwitchTabItem) + { + index = TabItems.Count - 1; + } + else + { + return; + } } if (!ClickTabToNavigation) @@ -683,15 +696,22 @@ public void ClickNextTab() var index = TabItems.IndexOf(item); if (index < TabItems.Count) { - if (!ClickTabToNavigation) + index++; + if (index + 1 > TabItems.Count) { - item.SetActive(false); + if (IsLoopSwitchTabItem) + { + index = 0; + } + else + { + return; + } } - index++; - if (index + 1 > TabItems.Count) + if (!ClickTabToNavigation) { - index = 0; + item.SetActive(false); } item = TabItems[index]; diff --git a/test/UnitTest/Components/TabTest.cs b/test/UnitTest/Components/TabTest.cs index bc2dc19f0f3..5b47d65a928 100644 --- a/test/UnitTest/Components/TabTest.cs +++ b/test/UnitTest/Components/TabTest.cs @@ -171,6 +171,42 @@ public void IsBorderCard_Ok() Assert.Contains("tabs-border-card", cut.Markup); } + [Fact] + public async Task IsLoopSwitchTabItem_Ok() + { + var cut = Context.RenderComponent(pb => + { + pb.Add(a => a.ShowExtendButtons, true); + pb.Add(a => a.IsLoopSwitchTabItem, false); + pb.AddChildContent(pb => + { + pb.Add(a => a.Text, "Tab1"); + pb.Add(a => a.Url, "/Index"); + pb.Add(a => a.ChildContent, "Tab1-Content"); + }); + pb.AddChildContent(pb => + { + pb.Add(a => a.Text, "Tab2"); + pb.Add(a => a.Url, "/"); + pb.Add(a => a.ChildContent, "Tab2-Content"); + }); + }); + Assert.Equal("Tab2-Content", cut.Find(".tabs-body .d-none").InnerHtml); + + // Click Prev + var button = cut.Find(".nav-link-bar.left .nav-link-bar-button"); + await cut.InvokeAsync(() => button.Click()); + Assert.Equal("Tab2-Content", cut.Find(".tabs-body .d-none").InnerHtml); + + // Click Next + button = cut.Find(".nav-link-bar.right .nav-link-bar-button"); + await cut.InvokeAsync(() => button.Click()); + Assert.Equal("Tab1-Content", cut.Find(".tabs-body .d-none").InnerHtml); + + await cut.InvokeAsync(() => button.Click()); + Assert.Equal("Tab1-Content", cut.Find(".tabs-body .d-none").InnerHtml); + } + [Fact] public void ClickTab_Ok() {