Skip to content

Commit 49c22b0

Browse files
committed
feat(uiSrefActive): Added support for multiple nested uiSref directives
1 parent 030f4df commit 49c22b0

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
@@ -107,7 +107,7 @@ function $StateRefDirective($state, $timeout) {
107107

108108
var activeDirective = uiSrefActive[1] || uiSrefActive[0];
109109
if (activeDirective) {
110-
activeDirective.$$setStateInfo(ref.state, params);
110+
activeDirective.$$addStateInfo(ref.state, params);
111111
}
112112
if (newHref === null) {
113113
nav = false;
@@ -226,36 +226,50 @@ function $StateRefActiveDirective($state, $stateParams, $interpolate) {
226226
return {
227227
restrict: "A",
228228
controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
229-
var state, params, activeClass;
229+
var states = [], activeClass;
230230

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

236236
// Allow uiSref to communicate with uiSrefActive[Equals]
237-
this.$$setStateInfo = function (newState, newParams) {
238-
state = $state.get(newState, stateContext($element));
239-
params = newParams;
240-
update();
237+
this.$$addStateInfo = function (newState, newParams) {
238+
var state = $state.get(newState, stateContext($element));
239+
if (state) {
240+
states.push({
241+
state: state,
242+
params: newParams
243+
});
244+
update();
245+
}
241246
};
242247

243248
$scope.$on('$stateChangeSuccess', update);
244249

245250
// Update route state
246251
function update() {
247-
if (isMatch()) {
252+
if (anyMatch()) {
248253
$element.addClass(activeClass);
249254
} else {
250255
$element.removeClass(activeClass);
251256
}
252257
}
253258

254-
function isMatch() {
259+
function anyMatch() {
260+
for (var i = 0; i < states.length; i++) {
261+
if (isMatch(states[i].state, states[i].params)) {
262+
return true;
263+
}
264+
}
265+
return false;
266+
}
267+
268+
function isMatch(state, params) {
255269
if (typeof $attrs.uiSrefActiveEq !== 'undefined') {
256-
return state && $state.is(state.name, params);
270+
return $state.is(state.name, params);
257271
} else {
258-
return state && $state.includes(state.name, params);
272+
return $state.includes(state.name, params);
259273
}
260274
}
261275
}]

test/stateDirectivesSpec.js

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

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

0 commit comments

Comments
 (0)