diff --git a/src/directives/stateDirectives.ts b/src/directives/stateDirectives.ts
index 78e67d552..f6ae66c54 100644
--- a/src/directives/stateDirectives.ts
+++ b/src/directives/stateDirectives.ts
@@ -511,6 +511,17 @@ uiStateDirective = ['$uiRouter', '$timeout',
*
* ```
*
+ * Arrays are also supported as values in the `ngClass`-like interface.
+ * This allows multiple states to add `active` class.
+ *
+ * #### Example:
+ * Given the following template, with "admin.roles" being the current state, the class will be added too:
+ * ```html
+ *
+ * ```
+ *
* When the current state is "admin.roles" the "active" class will be applied to both the `` and `
` elements.
* It is important to note that the state names/globs passed to `ui-sref-active` override any state provided by a linked `ui-sref`.
*
@@ -545,11 +556,21 @@ uiSrefActiveDirective = ['$state', '$stateParams', '$interpolate', '$uiRouter',
}
uiSrefActive = uiSrefActive || $interpolate($attrs.uiSrefActive || '', false)($scope);
if (isObject(uiSrefActive)) {
- forEach(uiSrefActive, function (stateOrName: StateOrName, activeClass: string) {
- if (isString(stateOrName)) {
+ forEach(uiSrefActive, function (stateOrName: StateOrName|Array, activeClass: string) {
+ // Helper function to abstract adding state.
+ const addStateForClass = function (stateOrName: string, activeClass: string) {
const ref = parseStateRef(stateOrName);
addState(ref.state, $scope.$eval(ref.paramExpr), activeClass);
}
+ if (isString(stateOrName)) {
+ // If state is string, just add it.
+ addStateForClass(stateOrName as string, activeClass)
+ } else if (isArray(stateOrName)) {
+ // If state is an array, iterate over it and add each array item individually.
+ forEach(stateOrName, function (stateOrName: string) {
+ addStateForClass(stateOrName, activeClass)
+ });
+ }
});
}
diff --git a/test/stateDirectivesSpec.js b/test/stateDirectivesSpec.js
index 5c4bb3f17..885cded6b 100644
--- a/test/stateDirectivesSpec.js
+++ b/test/stateDirectivesSpec.js
@@ -1112,4 +1112,49 @@ describe('uiSrefActive', function() {
expect(el.hasClass('active')).toBeTruthy();
}));
});
+
+ describe('ng-{class,style} interface, and handle values as arrays', function() {
+ it('should match on abstract states that are included by the current state', inject(function($rootScope, $compile, $state, $q) {
+ el = $compile('')($rootScope);
+ $state.transitionTo('admin.roles');
+ $q.flush();
+ timeoutFlush();
+ var abstractParent = el[0];
+ expect(abstractParent.className).toMatch(/active/);
+ var child = el[0].querySelector('a');
+ expect(child.className).toMatch(/active/);
+ }));
+
+ it('should match on state parameters', inject(function($compile, $rootScope, $state, $q) {
+ el = $compile('')($rootScope);
+ $state.transitionTo('admin.roles', {page: 1});
+ $q.flush();
+ timeoutFlush();
+ expect(el[0].className).toMatch(/active/);
+ }));
+
+ it('should support multiple pairs', inject(function($compile, $rootScope, $state, $q) {
+ el = $compile('')($rootScope);
+ $state.transitionTo('contacts.item.detail', {id: 1, foo: 'bar'});
+ $q.flush();
+ timeoutFlush();
+ expect(el[0].className).toMatch(/contacts/);
+ expect(el[0].className).not.toMatch(/admin/);
+ $state.transitionTo('admin.roles', {page: 1});
+ $q.flush();
+ timeoutFlush();
+ expect(el[0].className).toMatch(/admin/);
+ expect(el[0].className).not.toMatch(/contacts/);
+ }));
+
+ it('should update the active classes when compiled', inject(function($compile, $rootScope, $document, $state, $q) {
+ $state.transitionTo('admin.roles');
+ $q.flush();
+ timeoutFlush();
+ el = $compile('')($rootScope);
+ $rootScope.$digest();
+ timeoutFlush();
+ expect(el.hasClass('active')).toBeTruthy();
+ }));
+ });
});