From e6b42840511203b7d46675bf95579d15e1bad196 Mon Sep 17 00:00:00 2001 From: Nadezhda Tacheva Date: Wed, 4 Jun 2025 14:57:48 +0300 Subject: [PATCH 1/3] chore(TabStrip): add kb for adding and removing tabs --- components/tabstrip/tabs-collection.md | 17 +- knowledge-base/tabstrip-add-remove-tabs.md | 171 +++++++++++++++++++++ knowledge-base/tabstrip-dynamic-tabs.md | 31 ---- 3 files changed, 182 insertions(+), 37 deletions(-) create mode 100644 knowledge-base/tabstrip-add-remove-tabs.md delete mode 100644 knowledge-base/tabstrip-dynamic-tabs.md diff --git a/components/tabstrip/tabs-collection.md b/components/tabstrip/tabs-collection.md index 77d740a82a..a795e7ead2 100644 --- a/components/tabstrip/tabs-collection.md +++ b/components/tabstrip/tabs-collection.md @@ -27,7 +27,7 @@ To deactivate all tabs, set the ActiveTabId parameter to `string.Empty`. @{ foreach (var tab in Tabs) { - + @tab.Title @@ -54,11 +54,11 @@ To deactivate all tabs, set the ActiveTabId parameter to `string.Empty`. private string ActiveTabId { get; set; } private List Tabs { get; set; } = new List -{ - new Tab { Id = "home", Title = "🏠 Home", Visible = true, Disabled = false }, - new Tab { Id = "profile", Title = "👤 Profile", Visible = true, Disabled = false }, - new Tab { Id = "settings", Title = "⚙️ Settings", Visible = true, Disabled = false } -}; + { + new Tab { Id = "home", Title = "🏠 Home", Visible = true, Disabled = false }, + new Tab { Id = "profile", Title = "👤 Profile", Visible = true, Disabled = false }, + new Tab { Id = "settings", Title = "⚙️ Settings", Visible = true, Disabled = false } + }; public class Tab { @@ -70,6 +70,11 @@ To deactivate all tabs, set the ActiveTabId parameter to `string.Empty`. } ```` +## Add and Remove Tabs + +If you are iterating through a collection to render the tabs and you need to allow the users to add and remove tabs, you may use the `ActiveTabId` parameter to set the active tab after adding and removing tabs. See details and example in this article: [Add and Remove Tabs](slug:tabstrip-kb-add-remove-tabs). + + ## See Also * [TabStrip Events](slug:tabstrip-events) diff --git a/knowledge-base/tabstrip-add-remove-tabs.md b/knowledge-base/tabstrip-add-remove-tabs.md new file mode 100644 index 0000000000..d9404d7d1c --- /dev/null +++ b/knowledge-base/tabstrip-add-remove-tabs.md @@ -0,0 +1,171 @@ +--- +title: Add and Remove Tabs +description: Learn how to dynamically add and remove tabs +type: how-to +page_title: Add and Remove Tabs +slug: tabstrip-kb-add-remove-tabs +tags: telerik,blazor,tabstrip,add tabs,remove tabs +ticketid: +res_type: kb +previous_url: /knowledge-base/tabstrip-dynamic-tabs +--- + +## Environment + + + + + + + + +
ProductTabStrip for Blazor
+ + +## Description + +I have a collection of items representing separate tabs. I am iterating through that collection to render a tab for each item as shown [here](slug:tabstrip-tabs-collection). I want to allow the user to add and remove tabs, how to achieve that? + +This KB article answers the following questions: + +* How to remove a tab with a "X" button in the tab header? +* How to use a button to add tabs and position this button next to the last tab header (similar to the "+" button in the browser)? + +## Solution + +The example below shows how to: +* Use a [`HeaderTemplate`](slug:tabstrip-header-template) for the tab to add a button that removes the tab. +* Conditionally display the "X" button based on the tabs' count. +* Declare a button for adding tabs. +* Use custom styling and JavaScript to position the "+" button next to the last tab header. + +````RAZOR +@inject IJSRuntime JS + + + +
+ + + @foreach (Tab tab in Tabs) + { + + +
+ @tab.Title + @if (Tabs.Count > 1) + { + + } +
+
+ + Content for @tab.Title + +
+ } +
+
+ +@code { + private string ActiveTabId { get; set; } + + private List Tabs = new List() + { + new Tab { Id = Guid.NewGuid().ToString(), Title = "Tab 1" }, + new Tab { Id = Guid.NewGuid().ToString(), Title = "Tab 2" }, + new Tab { Id = Guid.NewGuid().ToString(), Title = "Tab 3" } + }; + + private void AddTab() + { + Tab tabToAdd = new Tab { Id = Guid.NewGuid().ToString(), Title = $"New Tab" }; + + Tabs.Add(tabToAdd); + + //In this example, we are always activating the newly added tab. Adjust the logic to activate a different tab if needed. + ActiveTabId = tabToAdd.Id; + } + + private void RemoveTab(Tab tab) + { + if (Tabs.Count <= 1) + { + return; + } + + Tabs.Remove(tab); + + //In this example, we are always activating the first tab. Adjust the logic to determine which tab to activate after removal. + ActiveTabId = Tabs[0].Id; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await JS.InvokeVoidAsync("positionAddTabButton"); + + await base.OnAfterRenderAsync(firstRender); + } + + public class Tab + { + public string Id { get; set; } + + public string Title { get; set; } + } + +} + + +```` + +## See Also + +* [Dynamic Tabs](slug:tabstrip-tabs-collection) \ No newline at end of file diff --git a/knowledge-base/tabstrip-dynamic-tabs.md b/knowledge-base/tabstrip-dynamic-tabs.md deleted file mode 100644 index b2ae2f693b..0000000000 --- a/knowledge-base/tabstrip-dynamic-tabs.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Dynamic Tabs -description: How to create Dynamic Tabs in TabStip. -type: how-to -page_title: Dynamic Tabs -slug: tabstrip-kb-dynamic-tabs -position: -tags: -res_type: kb ---- - -## Environment - - - - - - - - -
ProductTabStrip for Blazor
- - -## Description - -How to create Dynamic Tabs in TabStip? How to add and remove tabs dynamically? How to get information about the currently active tab? How to set the content of the tabs dynamically? - - -## Solution - -An example is available in the following project: [https://github.com/telerik/blazor-ui/tree/master/tabstrip/DynamicTabs](https://github.com/telerik/blazor-ui/tree/master/tabstrip/DynamicTabs). \ No newline at end of file From e28ffa6f52e7e96f7e53084524063bd6bfc44178 Mon Sep 17 00:00:00 2001 From: Tsvetomir Hristov <106250052+Tsvetomir-Hr@users.noreply.github.com> Date: Fri, 13 Jun 2025 12:10:35 +0300 Subject: [PATCH 2/3] chore: polish the example and update article content --- knowledge-base/tabstrip-add-remove-tabs.md | 123 ++++++++++----------- 1 file changed, 60 insertions(+), 63 deletions(-) diff --git a/knowledge-base/tabstrip-add-remove-tabs.md b/knowledge-base/tabstrip-add-remove-tabs.md index d9404d7d1c..97695ac1ef 100644 --- a/knowledge-base/tabstrip-add-remove-tabs.md +++ b/knowledge-base/tabstrip-add-remove-tabs.md @@ -24,44 +24,25 @@ previous_url: /knowledge-base/tabstrip-dynamic-tabs ## Description -I have a collection of items representing separate tabs. I am iterating through that collection to render a tab for each item as shown [here](slug:tabstrip-tabs-collection). I want to allow the user to add and remove tabs, how to achieve that? +I have a collection of items representing separate tabs. I am iterating through that collection to render a tab for each item as shown in the [Tabs Collection article](slug:tabstrip-tabs-collection). I want to allow the user to add and remove tabs. How to achieve that? -This KB article answers the following questions: +This KB article also answers the following questions: -* How to remove a tab with a "X" button in the tab header? -* How to use a button to add tabs and position this button next to the last tab header (similar to the "+" button in the browser)? +* How to implement add and remove tab functionality with the Telerik TabStrip component. +* How to remove a tab using an "X" button in the tab header. +* How to add a new tab with a "+" button, similar to browser tab controls. +* How to position the add ("+") button next to the last tab header. ## Solution -The example below shows how to: -* Use a [`HeaderTemplate`](slug:tabstrip-header-template) for the tab to add a button that removes the tab. -* Conditionally display the "X" button based on the tabs' count. -* Declare a button for adding tabs. +* Use a [`HeaderTemplate`](slug:tabstrip-header-template) for the tab to add an "X" button. +* Display the "X" button only when there is more than one tab. +* Declare a "+" button for adding tabs. * Use custom styling and JavaScript to position the "+" button next to the last tab header. ````RAZOR @inject IJSRuntime JS - -
+ + + + @code { - private string ActiveTabId { get; set; } + private string ActiveTabId { get; set; } = string.Empty; - private List Tabs = new List() + private List Tabs = new List { new Tab { Id = Guid.NewGuid().ToString(), Title = "Tab 1" }, new Tab { Id = Guid.NewGuid().ToString(), Title = "Tab 2" }, @@ -106,11 +129,10 @@ The example below shows how to: private void AddTab() { - Tab tabToAdd = new Tab { Id = Guid.NewGuid().ToString(), Title = $"New Tab" }; - + var tabToAdd = new Tab { Id = Guid.NewGuid().ToString(), Title = "New Tab" }; Tabs.Add(tabToAdd); - //In this example, we are always activating the newly added tab. Adjust the logic to activate a different tab if needed. + // Activate the newly added tab ActiveTabId = tabToAdd.Id; } @@ -119,51 +141,26 @@ The example below shows how to: if (Tabs.Count <= 1) { return; - } - + } + Tabs.Remove(tab); - //In this example, we are always activating the first tab. Adjust the logic to determine which tab to activate after removal. + // Activate the first tab after removal ActiveTabId = Tabs[0].Id; } protected override async Task OnAfterRenderAsync(bool firstRender) { await JS.InvokeVoidAsync("positionAddTabButton"); - await base.OnAfterRenderAsync(firstRender); } public class Tab { - public string Id { get; set; } - - public string Title { get; set; } + public string Id { get; set; } = string.Empty; + public string Title { get; set; } = string.Empty; } - } - - ```` ## See Also From 7b9f4ac320ac86b7a9f80974239897587e4c9241 Mon Sep 17 00:00:00 2001 From: Dimo Dimov <961014+dimodi@users.noreply.github.com> Date: Fri, 13 Jun 2025 13:00:43 +0300 Subject: [PATCH 3/3] polish KB article --- ...emove-tabs.md => tabstrip-dynamic-tabs.md} | 113 +++++++++++------- 1 file changed, 72 insertions(+), 41 deletions(-) rename knowledge-base/{tabstrip-add-remove-tabs.md => tabstrip-dynamic-tabs.md} (53%) diff --git a/knowledge-base/tabstrip-add-remove-tabs.md b/knowledge-base/tabstrip-dynamic-tabs.md similarity index 53% rename from knowledge-base/tabstrip-add-remove-tabs.md rename to knowledge-base/tabstrip-dynamic-tabs.md index 97695ac1ef..d8b8895053 100644 --- a/knowledge-base/tabstrip-add-remove-tabs.md +++ b/knowledge-base/tabstrip-dynamic-tabs.md @@ -1,13 +1,12 @@ --- -title: Add and Remove Tabs +title: Add and Remove TabStrip Tabs description: Learn how to dynamically add and remove tabs type: how-to -page_title: Add and Remove Tabs +page_title: How to Add and Remove TabStrip Tabs slug: tabstrip-kb-add-remove-tabs tags: telerik,blazor,tabstrip,add tabs,remove tabs -ticketid: +ticketid: res_type: kb -previous_url: /knowledge-base/tabstrip-dynamic-tabs --- ## Environment @@ -21,7 +20,6 @@ previous_url: /knowledge-base/tabstrip-dynamic-tabs - ## Description I have a collection of items representing separate tabs. I am iterating through that collection to render a tab for each item as shown in the [Tabs Collection article](slug:tabstrip-tabs-collection). I want to allow the user to add and remove tabs. How to achieve that? @@ -35,10 +33,12 @@ This KB article also answers the following questions: ## Solution -* Use a [`HeaderTemplate`](slug:tabstrip-header-template) for the tab to add an "X" button. -* Display the "X" button only when there is more than one tab. -* Declare a "+" button for adding tabs. -* Use custom styling and JavaScript to position the "+" button next to the last tab header. +1. [Render the TabStrip tabs in a loop](slug:tabstrip-tabs-collection). +1. Use a [`HeaderTemplate`](slug:tabstrip-header-template) for the tabs to add Remove buttons. You can display the buttons conditionally based on the tab count. +1. Declare a button for adding new tabs. +1. Use custom styling and JavaScript to position the Add button next to the last tab header. + +>caption Adding and removing TabStrip tabs at runtime ````RAZOR @inject IJSRuntime JS @@ -46,29 +46,30 @@ This KB article also answers the following questions:
+ Icon="@SvgIcon.Plus" + ThemeColor="@ThemeConstants.Button.ThemeColor.Primary" /> + @foreach (Tab tab in Tabs) {
- @tab.Title + @tab.Title @if (Tabs.Count > 1) { }
- Content for @tab.Title + Content for @tab.Title
} @@ -95,45 +96,54 @@ This KB article also answers the following questions: } +@* Move JavaScript code to a JS file *@ -@code { - private string ActiveTabId { get; set; } = string.Empty; - private List Tabs = new List +@code { + private List Tabs = new List() { - new Tab { Id = Guid.NewGuid().ToString(), Title = "Tab 1" }, - new Tab { Id = Guid.NewGuid().ToString(), Title = "Tab 2" }, - new Tab { Id = Guid.NewGuid().ToString(), Title = "Tab 3" } + new Tab { Title = "Tab 1" }, + new Tab { Title = "Tab 2" }, + new Tab { Title = "Tab 3" } }; + private string ActiveTabId { get; set; } = string.Empty; + + private bool ShouldPositionAddButton { get; set; } + + private int LastTabNumber { get; set; } = 3; + private void AddTab() { - var tabToAdd = new Tab { Id = Guid.NewGuid().ToString(), Title = "New Tab" }; + Tab tabToAdd = new Tab { Id = Guid.NewGuid().ToString(), Title = $"New Tab {++LastTabNumber}" }; + Tabs.Add(tabToAdd); - // Activate the newly added tab + //In this example, we are always activating the newly added tab. Adjust the logic to activate a different tab if needed. ActiveTabId = tabToAdd.Id; + + ShouldPositionAddButton = true; } private void RemoveTab(Tab tab) @@ -143,26 +153,47 @@ This KB article also answers the following questions: return; } + // Activate the tab after or before the removed one if it's active + if (ActiveTabId == tab.Id) + { + int removedTabIndex = Tabs.FindIndex(x => x.Id == tab.Id); + if (removedTabIndex == Tabs.Count - 1) + { + ActiveTabId = Tabs.ElementAt(removedTabIndex - 1).Id; + } + else + { + ActiveTabId = Tabs.ElementAt(removedTabIndex + 1).Id; + } + } + Tabs.Remove(tab); - // Activate the first tab after removal - ActiveTabId = Tabs[0].Id; + ShouldPositionAddButton = true; } protected override async Task OnAfterRenderAsync(bool firstRender) { - await JS.InvokeVoidAsync("positionAddTabButton"); + if (firstRender || ShouldPositionAddButton) + { + ShouldPositionAddButton = false; + await JS.InvokeVoidAsync("positionAddTabButton"); + } + await base.OnAfterRenderAsync(firstRender); } public class Tab { - public string Id { get; set; } = string.Empty; + public string Id { get; set; } = Guid.NewGuid().ToString(); + public string Title { get; set; } = string.Empty; } + } ```` ## See Also -* [Dynamic Tabs](slug:tabstrip-tabs-collection) \ No newline at end of file +* [Dynamic Tab Collection](slug:tabstrip-tabs-collection) +* [TabStrip Tab `HeaderTemplate`](slug:tabstrip-header-template)