diff --git a/src/tabs/docs/readme.md b/src/tabs/docs/readme.md index 0bdbfeb9ed..d7681a95be 100644 --- a/src/tabs/docs/readme.md +++ b/src/tabs/docs/readme.md @@ -33,7 +33,7 @@ AngularJS version of the tabs directive. * `deselect()` $ - - An optional expression called when tab is deactivated. Supports $event in template for expression. + An optional expression called when tab is deactivated. Supports $event in template for expression. You may call `$event.preventDefault()` in this event handler to prevent a tab change from occurring. * `disable` $ diff --git a/src/tabs/tabs.js b/src/tabs/tabs.js index adf3c5c7a6..06cc9b6e43 100644 --- a/src/tabs/tabs.js +++ b/src/tabs/tabs.js @@ -13,6 +13,9 @@ angular.module('ui.bootstrap.tabs', []) previousSelected.tab.onDeselect({ $event: evt }); + if (evt && evt.defaultPrevented) { + return; + } previousSelected.tab.active = false; } diff --git a/src/tabs/test/tabs.spec.js b/src/tabs/test/tabs.spec.js index f2e7642e11..9e89846bd6 100644 --- a/src/tabs/test/tabs.spec.js +++ b/src/tabs/test/tabs.spec.js @@ -33,6 +33,7 @@ describe('tabs', function() { scope = $rootScope.$new(); scope.first = '1'; scope.second = '2'; + scope.third = '3'; scope.active = 1; scope.firstClass = 'first-class'; scope.secondClass = 'second-class-1 second-class-2'; @@ -40,6 +41,9 @@ describe('tabs', function() { scope.selectSecond = jasmine.createSpy(); scope.deselectFirst = jasmine.createSpy(); scope.deselectSecond = jasmine.createSpy(); + scope.deselectThird = function($event) { + $event.preventDefault(); + }; elm = $compile([ '', ' ', @@ -49,6 +53,10 @@ describe('tabs', function() { ' Second Tab {{second}}', ' second content is {{second}}', ' ', + ' ', + ' Second Tab {{third}}', + ' third content is {{third}}', + ' ', '' ].join('\n'))(scope); scope.$apply(); @@ -65,7 +73,7 @@ describe('tabs', function() { it('should create clickable titles', function() { var t = titles(); - expect(t.length).toBe(2); + expect(t.length).toBe(3); expect(t.find('> a').eq(0).text()).toBe('First Tab 1'); //It should put the uib-tab-heading element into the 'a' title expect(t.find('> a').eq(1).children().is('uib-tab-heading')).toBe(true); @@ -73,7 +81,7 @@ describe('tabs', function() { }); it('should bind tabs content and set first tab active', function() { - expectContents(['first content is 1', 'second content is 2']); + expectContents(['first content is 1', 'second content is 2', 'third content is 3']); expect(titles().eq(0)).toHaveClass('active'); expect(titles().eq(1)).not.toHaveClass('active'); expect(scope.active).toBe(1); @@ -117,6 +125,16 @@ describe('tabs', function() { expect(scope.deselectFirst.calls.count()).toBe(2); expect(scope.deselectFirst.calls.argsFor(1)[0].target).toBe(titles().eq(1).find('> a')[0]); }); + + it('should prevent tab deselection when $event.preventDefault() is called', function() { + spyOn(scope, 'deselectThird'); + titles().eq(2).find('> a').click(); + expect(scope.active).toBe(3); + titles().eq(1).find('> a').click(); + expect(scope.deselectThird).toHaveBeenCalled(); + expect(scope.active).not.toBe(1); + expect(scope.active).toBe(2); + }); }); describe('basics with initial active tab', function() {