Skip to content

Commit b184494

Browse files
committed
feat(uiSrefActive): Added support for multiple nested uiSref directives
1 parent 0250291 commit b184494

File tree

2 files changed

+40
-10
lines changed

2 files changed

+40
-10
lines changed

src/stateDirectives.js

+24-10
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ function $StateRefDirective($state, $timeout) {
110110

111111
var activeDirective = uiSrefActive[1] || uiSrefActive[0];
112112
if (activeDirective) {
113-
activeDirective.$$setStateInfo(ref.state, params);
113+
activeDirective.$$addStateInfo(ref.state, params);
114114
}
115115
if (newHref === null) {
116116
nav = false;
@@ -229,36 +229,50 @@ function $StateRefActiveDirective($state, $stateParams, $interpolate) {
229229
return {
230230
restrict: "A",
231231
controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
232-
var state, params, activeClass;
232+
var states = [], activeClass;
233233

234234
// There probably isn't much point in $observing this
235235
// uiSrefActive and uiSrefActiveEq share the same directive object with some
236236
// slight difference in logic routing
237237
activeClass = $interpolate($attrs.uiSrefActiveEq || $attrs.uiSrefActive || '', false)($scope);
238238

239239
// Allow uiSref to communicate with uiSrefActive[Equals]
240-
this.$$setStateInfo = function (newState, newParams) {
241-
state = $state.get(newState, stateContext($element));
242-
params = newParams;
243-
update();
240+
this.$$addStateInfo = function (newState, newParams) {
241+
var state = $state.get(newState, stateContext($element));
242+
if (state) {
243+
states.push({
244+
state: state,
245+
params: newParams
246+
});
247+
update();
248+
}
244249
};
245250

246251
$scope.$on('$stateChangeSuccess', update);
247252

248253
// Update route state
249254
function update() {
250-
if (isMatch()) {
255+
if (anyMatch()) {
251256
$element.addClass(activeClass);
252257
} else {
253258
$element.removeClass(activeClass);
254259
}
255260
}
256261

257-
function isMatch() {
262+
function anyMatch() {
263+
for (var i = 0; i < states.length; i++) {
264+
if (isMatch(states[i].state, states[i].params)) {
265+
return true;
266+
}
267+
}
268+
return false;
269+
}
270+
271+
function isMatch(state, params) {
258272
if (typeof $attrs.uiSrefActiveEq !== 'undefined') {
259-
return state && $state.is(state.name, params);
273+
return $state.is(state.name, params);
260274
} else {
261-
return state && $state.includes(state.name, params);
275+
return $state.includes(state.name, params);
262276
}
263277
}
264278
}]

test/stateDirectivesSpec.js

+16
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,22 @@ describe('uiSrefActive', function() {
495495
$q.flush();
496496
expect(angular.element(template[0].querySelector('a')).attr('class')).toBe('ng-scope');
497497
}));
498+
499+
it('should match on any child state refs', inject(function($rootScope, $q, $compile, $state) {
500+
el = angular.element('<div ui-sref-active="active"><a ui-sref="contacts.item({ id: 1 })">Contacts</a><a ui-sref="contacts.item({ id: 2 })">Contacts</a></div>');
501+
template = $compile(el)($rootScope);
502+
$rootScope.$digest();
503+
504+
expect(angular.element(template[0]).attr('class')).toBe('ng-scope');
505+
506+
$state.transitionTo('contacts.item', { id: 1 });
507+
$q.flush();
508+
expect(angular.element(template[0]).attr('class')).toBe('ng-scope active');
509+
510+
$state.transitionTo('contacts.item', { id: 2 });
511+
$q.flush();
512+
expect(angular.element(template[0]).attr('class')).toBe('ng-scope active');
513+
}));
498514
});
499515

500516
describe('uiView controllers or onEnter handlers', function() {

0 commit comments

Comments
 (0)