diff --git a/src/tabs/tabs.js b/src/tabs/tabs.js index db998b0d47..dbda75ca29 100644 --- a/src/tabs/tabs.js +++ b/src/tabs/tabs.js @@ -196,8 +196,13 @@ angular.module('ui.bootstrap.tabs', []) if (attrs.active) { getActive = $parse(attrs.active); setActive = getActive.assign; - scope.$parent.$watch(getActive, function updateActive(value) { - scope.active = !!value; + scope.$parent.$watch(getActive, function updateActive(value, oldVal) { + // Avoid re-initializing scope.active as it is already initialized + // below. (watcher is called async during init with value === + // oldVal) + if (value !== oldVal) { + scope.active = !!value; + } }); scope.active = getActive(scope.$parent); } else { @@ -205,6 +210,8 @@ angular.module('ui.bootstrap.tabs', []) } scope.$watch('active', function(active) { + // Note this watcher also initializes and assigns scope.active to the + // attrs.active expression. setActive(scope.$parent, active); if (active) { tabsetCtrl.select(scope); @@ -231,9 +238,6 @@ angular.module('ui.bootstrap.tabs', []) scope.$on('$destroy', function() { tabsetCtrl.removeTab(scope); }); - if (scope.active) { - setActive(scope.$parent, true); - } //We need to transclude later, once the content container is ready. diff --git a/src/tabs/test/tabsSpec.js b/src/tabs/test/tabsSpec.js index 692d42a9f4..61215db39b 100644 --- a/src/tabs/test/tabsSpec.js +++ b/src/tabs/test/tabsSpec.js @@ -102,6 +102,57 @@ describe('tabs', function() { }); + describe('basics with initial active tab', function() { + + beforeEach(inject(function($compile, $rootScope) { + scope = $rootScope.$new(); + + function makeTab(active) { + return { + active: !!active, + select: jasmine.createSpy() + }; + } + scope.tabs = [ + makeTab(), makeTab(), makeTab(true), makeTab() + ]; + elm = $compile([ + '', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + '' + ].join('\n'))(scope); + scope.$apply(); + })); + + function expectTabActive(activeTab) { + var _titles = titles(); + angular.forEach(scope.tabs, function(tab, i) { + if (activeTab === tab) { + expect(tab.active).toBe(true); + //It should only call select ONCE for each select + expect(tab.select).toHaveBeenCalled(); + expect(_titles.eq(i)).toHaveClass('active'); + expect(contents().eq(i)).toHaveClass('active'); + } else { + expect(tab.active).toBe(false); + expect(_titles.eq(i)).not.toHaveClass('active'); + } + }); + } + + it('should make tab titles and set active tab active', function() { + expect(titles().length).toBe(scope.tabs.length); + expectTabActive(scope.tabs[2]); + }); + }); + describe('ng-repeat', function() { beforeEach(inject(function($compile, $rootScope) {