Skip to content

Commit 4c8a6d6

Browse files
committed
Allow arrays to be passed to uiSrefActive
1 parent 2396232 commit 4c8a6d6

File tree

2 files changed

+68
-2
lines changed

2 files changed

+68
-2
lines changed

src/directives/stateDirectives.ts

+23-2
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,17 @@ uiStateDirective = ['$uiRouter', '$timeout',
511511
* </div>
512512
* ```
513513
*
514+
* Arrays are also supported as values in the `ngClass`-like interface.
515+
* This allows multiple states to add `active` class.
516+
*
517+
* #### Example:
518+
* Given the following template, with "admin.roles" being the current state, the class will be added too:
519+
* ```html
520+
* <div ui-sref-active="{'active': ['owner.**', 'admin.**']}">
521+
* <a ui-sref-active="active" ui-sref="admin.roles">Roles</a>
522+
* </div>
523+
* ```
524+
*
514525
* When the current state is "admin.roles" the "active" class will be applied to both the `<div>` and `<a>` elements.
515526
* It is important to note that the state names/globs passed to `ui-sref-active` override any state provided by a linked `ui-sref`.
516527
*
@@ -545,11 +556,21 @@ uiSrefActiveDirective = ['$state', '$stateParams', '$interpolate', '$uiRouter',
545556
}
546557
uiSrefActive = uiSrefActive || $interpolate($attrs.uiSrefActive || '', false)($scope);
547558
if (isObject(uiSrefActive)) {
548-
forEach(uiSrefActive, function (stateOrName: StateOrName, activeClass: string) {
549-
if (isString(stateOrName)) {
559+
forEach(uiSrefActive, function (stateOrName: StateOrName|Array<StateOrName>, activeClass: string) {
560+
// Helper function to abstract adding state.
561+
const addStateForClass = function (stateOrName: string, activeClass: string) {
550562
const ref = parseStateRef(stateOrName);
551563
addState(ref.state, $scope.$eval(ref.paramExpr), activeClass);
552564
}
565+
if (isString(stateOrName)) {
566+
// If state is string, just add it.
567+
addStateForClass(stateOrName as string, activeClass)
568+
} else if (isArray(stateOrName)) {
569+
// If state is an array, iterate over it and add each array item individually.
570+
forEach(stateOrName, function (stateOrName: string) {
571+
addStateForClass(stateOrName, activeClass)
572+
});
573+
}
553574
});
554575
}
555576

test/stateDirectivesSpec.js

+45
Original file line numberDiff line numberDiff line change
@@ -1112,4 +1112,49 @@ describe('uiSrefActive', function() {
11121112
expect(el.hasClass('active')).toBeTruthy();
11131113
}));
11141114
});
1115+
1116+
describe('ng-{class,style} interface, and handle values as arrays', function() {
1117+
it('should match on abstract states that are included by the current state', inject(function($rootScope, $compile, $state, $q) {
1118+
el = $compile('<div ui-sref-active="{active: [\'randomState.**\', \'admin.roles\']}"><a ui-sref-active="active" ui-sref="admin.roles">Roles</a></div>')($rootScope);
1119+
$state.transitionTo('admin.roles');
1120+
$q.flush();
1121+
timeoutFlush();
1122+
var abstractParent = el[0];
1123+
expect(abstractParent.className).toMatch(/active/);
1124+
var child = el[0].querySelector('a');
1125+
expect(child.className).toMatch(/active/);
1126+
}));
1127+
1128+
it('should match on state parameters', inject(function($compile, $rootScope, $state, $q) {
1129+
el = $compile('<div ui-sref-active="{active: [\'admin.roles({page: 1})\']}"></div>')($rootScope);
1130+
$state.transitionTo('admin.roles', {page: 1});
1131+
$q.flush();
1132+
timeoutFlush();
1133+
expect(el[0].className).toMatch(/active/);
1134+
}));
1135+
1136+
it('should support multiple <className, stateOrName> pairs', inject(function($compile, $rootScope, $state, $q) {
1137+
el = $compile('<div ui-sref-active="{contacts: [\'contacts.item\', \'contacts.item.detail\'], admin: \'admin.roles({page: 1})\'}"></div>')($rootScope);
1138+
$state.transitionTo('contacts.item.detail', {id: 1, foo: 'bar'});
1139+
$q.flush();
1140+
timeoutFlush();
1141+
expect(el[0].className).toMatch(/contacts/);
1142+
expect(el[0].className).not.toMatch(/admin/);
1143+
$state.transitionTo('admin.roles', {page: 1});
1144+
$q.flush();
1145+
timeoutFlush();
1146+
expect(el[0].className).toMatch(/admin/);
1147+
expect(el[0].className).not.toMatch(/contacts/);
1148+
}));
1149+
1150+
it('should update the active classes when compiled', inject(function($compile, $rootScope, $document, $state, $q) {
1151+
$state.transitionTo('admin.roles');
1152+
$q.flush();
1153+
timeoutFlush();
1154+
el = $compile('<div ui-sref-active="{active: [\'admin.roles\', \'admin.someOtherState\']}"/>')($rootScope);
1155+
$rootScope.$digest();
1156+
timeoutFlush();
1157+
expect(el.hasClass('active')).toBeTruthy();
1158+
}));
1159+
});
11151160
});

0 commit comments

Comments
 (0)