Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Commit

Permalink
feat(tabs): support disabled state
Browse files Browse the repository at this point in the history
  • Loading branch information
bekos committed May 24, 2013
1 parent c690b83 commit 2b78dd1
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 13 deletions.
14 changes: 6 additions & 8 deletions src/tabs/docs/demo.html
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
<div ng-controller="TabsDemoCtrl">
Select a tab by setting active binding to true:
<br />
<button class="btn" ng-click="tabs[0].active = true">
Select second tab
</button>
<button class="btn" ng-click="tabs[1].active = true">
Select third tab
</button>
<br /><br />
<button class="btn btn-small" ng-click="tabs[0].active = true">Select second tab</button>
<button class="btn btn-small" ng-click="tabs[1].active = true">Select third tab</button>
<button class="btn btn-small" ng-click="tabs[1].disabled = ! tabs[1].disabled">Enable / Disable third tab</button>
<hr />

<tabset>
<tab heading="Static title">Static content</tab>
<tab ng-repeat="tab in tabs" heading="{{tab.title}}" active="tab.active">
<tab ng-repeat="tab in tabs" heading="{{tab.title}}" active="tab.active" disabled="tab.disabled">
{{tab.content}}
</tab>
<tab select="alertMe()">
Expand Down
2 changes: 1 addition & 1 deletion src/tabs/docs/demo.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
var TabsDemoCtrl = function ($scope) {
$scope.tabs = [
{ title:"Dynamic Title 1", content:"Dynamic content 1" },
{ title:"Dynamic Title 2", content:"Dynamic content 2" }
{ title:"Dynamic Title 2", content:"Dynamic content 2", disabled: true }
];

$scope.alertMe = function() {
Expand Down
2 changes: 1 addition & 1 deletion src/tabs/docs/readme.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
AngularJS version of the tabs directive.

Allows a `select` callback attribute, and `active` binding attribute.
Allows a `select` callback attribute, `active` binding attribute and `disabled` binding attribute.

Allows either `heading` text-heading as an attribute, or a `<tab-heading>` element inside as the heading.
17 changes: 15 additions & 2 deletions src/tabs/tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ function($parse, $http, $templateCache, $compile) {
getActive = $parse(attrs.active);
setActive = getActive.assign;
scope.$parent.$watch(getActive, function updateActive(value) {
scope.active = !!value;
if ( !!value && scope.disabled ) {
setActive(scope.$parent, false); // Prevent active assignment
} else {
scope.active = !!value;
}
});
} else {
setActive = getActive = angular.noop;
Expand All @@ -85,8 +89,17 @@ function($parse, $http, $templateCache, $compile) {
}
});

scope.disabled = false;
if ( attrs.disabled ) {
scope.$parent.$watch($parse(attrs.disabled), function(value) {
scope.disabled = !! value;
});
}

scope.select = function() {
scope.active = true;
if ( ! scope.disabled ) {
scope.active = true;
}
};

tabsetCtrl.addTab(scope);
Expand Down
76 changes: 76 additions & 0 deletions src/tabs/test/tabsSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -378,4 +378,80 @@ describe('tabs', function() {
expect(contents().eq(2)).toHaveClass('active');
}));
});

describe('disabled', function() {
beforeEach(inject(function($compile, $rootScope) {
scope = $rootScope.$new();

function makeTab(disabled) {
return {
active: false,
select: jasmine.createSpy(),
disabled: disabled
};
}
scope.tabs = [
makeTab(false), makeTab(true), makeTab(false), makeTab(true)
];
elm = $compile([
'<tabset>',
' <tab ng-repeat="t in tabs" active="t.active" select="t.select()" disabled="t.disabled">',
' <tab-heading><b>heading</b> {{index}}</tab-heading>',
' content {{$index}}',
' </tab>',
'</tabset>'
].join('\n'))(scope);
scope.$apply();
}));

function titles() {
return elm.find('ul.nav-tabs li');
}
function contents() {
return elm.find('div.tab-content div.tab-pane');
}

function expectTabActive(activeTab) {
var _titles = titles();
angular.forEach(scope.tabs, function(tab, i) {
if (activeTab === tab) {
expect(tab.active).toBe(true);
expect(tab.select.callCount).toBe( (tab.disabled) ? 0 : 1 );
expect(_titles.eq(i)).toHaveClass('active');
expect(contents().eq(i).text().trim()).toBe('content ' + i);
expect(contents().eq(i)).toHaveClass('active');
} else {
expect(tab.active).toBe(false);
expect(_titles.eq(i)).not.toHaveClass('active');
}
});
}

it('should not switch active when clicking on title', function() {
titles().eq(2).find('a').click();
expectTabActive(scope.tabs[2]);

titles().eq(3).find('a').click();
expectTabActive(scope.tabs[2]);
});

it('should not switch active when setting active=true', function() {
scope.$apply('tabs[2].active = true');
expectTabActive(scope.tabs[2]);

scope.$apply('tabs[3].active = true');
expectTabActive(scope.tabs[2]);
});

it('should toggle between states', function() {
expect(titles().eq(3)).toHaveClass('disabled');
scope.$apply('tabs[3].disabled = false');
expect(titles().eq(3)).not.toHaveClass('disabled');

expect(titles().eq(2)).not.toHaveClass('disabled');
scope.$apply('tabs[2].disabled = true');
expect(titles().eq(2)).toHaveClass('disabled');
});
});

});
2 changes: 1 addition & 1 deletion template/tabs/tab.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<li ng-class="{active: active}">
<li ng-class="{active: active, disabled: disabled}">
<a ng-click="select()" tab-heading-transclude>{{heading}}</a>
</li>

0 comments on commit 2b78dd1

Please sign in to comment.