diff --git a/src/stateDirectives.js b/src/stateDirectives.js index 039b213b2..bced83073 100644 --- a/src/stateDirectives.js +++ b/src/stateDirectives.js @@ -147,13 +147,21 @@ function $StateActiveDirective($state, $stateParams, $interpolate) { // Update route state function update() { - if ($state.$current.self === state && matchesParams()) { + if (isMatch()) { $element.addClass(activeClass); } else { $element.removeClass(activeClass); } } + function isMatch() { + if (typeof $attrs.asParent !== 'undefined') { + return $state.includes(state.name) && matchesParams(); + } else { + return $state.$current.self === state && matchesParams(); + } + } + function matchesParams() { return !params || equalForKeys(params, $stateParams); } diff --git a/test/stateDirectivesSpec.js b/test/stateDirectivesSpec.js index f4e10a012..992ad0076 100644 --- a/test/stateDirectivesSpec.js +++ b/test/stateDirectivesSpec.js @@ -278,6 +278,8 @@ describe('uiSrefActive', function() { url: '/:id', }).state('contacts.item.detail', { url: '/detail/:foo' + }).state('contacts.item.edit', { + url: '/edit' }); })); @@ -316,6 +318,20 @@ describe('uiSrefActive', function() { expect(angular.element(template[0].querySelector('a')).attr('class')).toBe(''); })); + it('should match child states when asParent attribute is used', inject(function($rootScope, $q, $compile, $state) { + template = $compile('
Contacts
')($rootScope); + $rootScope.$digest(); + var a = angular.element(template[0].getElementsByTagName('a')[0]); + + $state.transitionTo('contacts.item.edit', { id: 1 }); + $q.flush(); + expect(a.attr('class')).toMatch(/active/); + + $state.transitionTo('contacts.item.edit', { id: 4 }); + $q.flush(); + expect(a.attr('class')).not.toMatch(/active/); + })); + it('should resolve relative state refs', inject(function($rootScope, $q, $compile, $state) { el = angular.element('
'); template = $compile(el)($rootScope);