diff --git a/src/stateDirectives.js b/src/stateDirectives.js index 27159274f..cc8359612 100644 --- a/src/stateDirectives.js +++ b/src/stateDirectives.js @@ -110,7 +110,7 @@ function $StateRefDirective($state, $timeout) { var activeDirective = uiSrefActive[1] || uiSrefActive[0]; if (activeDirective) { - activeDirective.$$setStateInfo(ref.state, params); + activeDirective.$$addStateInfo(ref.state, params); } if (newHref === null) { nav = false; @@ -229,7 +229,7 @@ function $StateRefActiveDirective($state, $stateParams, $interpolate) { return { restrict: "A", controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) { - var state, params, activeClass; + var states = [], activeClass; // There probably isn't much point in $observing this // uiSrefActive and uiSrefActiveEq share the same directive object with some @@ -237,28 +237,42 @@ function $StateRefActiveDirective($state, $stateParams, $interpolate) { activeClass = $interpolate($attrs.uiSrefActiveEq || $attrs.uiSrefActive || '', false)($scope); // Allow uiSref to communicate with uiSrefActive[Equals] - this.$$setStateInfo = function (newState, newParams) { - state = $state.get(newState, stateContext($element)); - params = newParams; - update(); + this.$$addStateInfo = function (newState, newParams) { + var state = $state.get(newState, stateContext($element)); + if (state) { + states.push({ + state: state, + params: newParams + }); + update(); + } }; $scope.$on('$stateChangeSuccess', update); // Update route state function update() { - if (isMatch()) { + if (anyMatch()) { $element.addClass(activeClass); } else { $element.removeClass(activeClass); } } - function isMatch() { + function anyMatch() { + for (var i = 0; i < states.length; i++) { + if (isMatch(states[i].state, states[i].params)) { + return true; + } + } + return false; + } + + function isMatch(state, params) { if (typeof $attrs.uiSrefActiveEq !== 'undefined') { - return state && $state.is(state.name, params); + return $state.is(state.name, params); } else { - return state && $state.includes(state.name, params); + return $state.includes(state.name, params); } } }] diff --git a/test/stateDirectivesSpec.js b/test/stateDirectivesSpec.js index 309da5612..90bed508b 100644 --- a/test/stateDirectivesSpec.js +++ b/test/stateDirectivesSpec.js @@ -495,6 +495,22 @@ describe('uiSrefActive', function() { $q.flush(); expect(angular.element(template[0].querySelector('a')).attr('class')).toBe('ng-scope'); })); + + it('should match on any child state refs', inject(function($rootScope, $q, $compile, $state) { + el = angular.element('
ContactsContacts
'); + template = $compile(el)($rootScope); + $rootScope.$digest(); + + expect(angular.element(template[0]).attr('class')).toBe('ng-scope'); + + $state.transitionTo('contacts.item', { id: 1 }); + $q.flush(); + expect(angular.element(template[0]).attr('class')).toBe('ng-scope active'); + + $state.transitionTo('contacts.item', { id: 2 }); + $q.flush(); + expect(angular.element(template[0]).attr('class')).toBe('ng-scope active'); + })); }); describe('uiView controllers or onEnter handlers', function() {