Setting active tab on dynamically created tabs with Angular UI Bootstrap

All we need is an easy explanation of the problem, so here it is.

I have a dynamic tabset that generates the tabs from an array which starts out blank. When I add a new item to the array it appears as a new tab. I want the last added tab to be the active one. I set the active index every time I add an item to the array

HTML:

<uib-tabset active="activeTabIndex">
    <uib-tab ng-repeat="tab in tabs" heading="{{tab.title}}">Some content</uib-tab>
</uib-tabset>

JavaScript:

$scope.activeTabIndex = 0
$scope.tabs = [];

$scope.addTab = function() {
    var newTab = {  title: 'Tab ' + ($scope.tabs.length + 1) };
    $scope.tabs.push(newTab); 
    $scope.activeTabIndex = ($scope.tabs.length - 1);
    console.log($scope.activeTabIndex);
};

Here’s the Plunk for the full source code of the demo: https://plnkr.co/edit/TX6ek4R62AfM2zUXcoC3?p=preview

The problem is it seems to be working with odd number of tabs only. Here’s what I mean:

On initial load it looks like this:

enter image description here

After I add a new tab it shows the active one correctly:

enter image description here

When I add another one nothing becomes selected and activeTabIndex variable becomes undefined:

enter image description here

And on the 3rd one it starts working again:

enter image description here

So for even active index numbers (0, 2) it works fine. But somehow instead of Acitve Index: 1 it shows blank and doesn’t set the active tab. I write the variable to console and it displays all the values correctly.

Any help/pointers/ideas are welcome.

Thanks.

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

According to docs:

active (Default: Index of first tab) – Active index of tab. Setting this to an existing tab index will make that tab active.

Ensure the tabs array contains the active one, I think you should add a $timeout there:

      $scope.addTab = function() {
        var newTab = {  title: 'Tab ' + ($scope.tabs.length + 1) };
        $scope.tabs.push(newTab); 
        $timeout(function(){
          $scope.activeTabIndex = ($scope.tabs.length - 1);
        });
        console.log($scope.activeTabIndex);
      };

https://plnkr.co/edit/q4QP7zoB0HXSjn3MplE4?p=preview

Method 2

I had the similar problem, But a little more Complex. I loaded my dynamic tabs from API, and I had one static tab and the rest were dynamic.

<uib-tabset active="activeTabIndex" ng-if="showTabs">
    <uib-tab heading="Static Heading">Static content</uib-tab>
    <uib-tab data-ng-repeat="tab in tabs" heading="{{tab.title}}">Some content</uib-tab>
</uib-tabset>

I used two variables with default values:

$scope.showTabs = false;
$scope.activeTabIndex = 0;

First, I loaded my dynamic tabs from API, Then in the success callback, I specified the value of activeTabIndex from tabs array. Then I changed the value of showTabs to true.

I shared it, just hope it can help more people with this case.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply