Skip to content

Commit abb3deb

Browse files
fix(ui-state): update ui-sref-active/eq info
when ui-state dynamicly changes watchers, make sure to update the ui-sref-active/eq Closes #2488
1 parent 83d6661 commit abb3deb

File tree

2 files changed

+52
-7
lines changed

2 files changed

+52
-7
lines changed

src/stateDirectives.js

+16-4
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,17 @@ function $StateRefDynamicDirective($state, $timeout) {
173173
var group = [attrs.uiState, attrs.uiStateParams || null, attrs.uiStateOpts || null];
174174
var watch = '[' + group.map(function(val) { return val || 'null'; }).join(', ') + ']';
175175
var def = { state: null, params: null, options: null, href: null };
176+
var unlinkInfoFn = null;
176177

177178
function runStateRefLink (group) {
178179
def.state = group[0]; def.params = group[1]; def.options = group[2];
179180
def.href = $state.href(def.state, def.params, def.options);
180181

181-
if (active) active.$$addStateInfo(def.state, def.params);
182+
if (unlinkInfoFn) {
183+
unlinkInfoFn();
184+
unlinkInfoFn = null;
185+
}
186+
if (active) unlinkInfoFn = active.$$addStateInfo(def.state, def.params);
182187
if (def.href) attrs.$set(type.attr, def.href);
183188
}
184189

@@ -319,8 +324,9 @@ function $StateRefActiveDirective($state, $stateParams, $interpolate) {
319324
if (isObject(uiSrefActive) && states.length > 0) {
320325
return;
321326
}
322-
addState(newState, newParams, uiSrefActive);
327+
var deregister = addState(newState, newParams, uiSrefActive);
323328
update();
329+
return deregister;
324330
};
325331

326332
$scope.$on('$stateChangeSuccess', update);
@@ -329,13 +335,19 @@ function $StateRefActiveDirective($state, $stateParams, $interpolate) {
329335
var state = $state.get(stateName, stateContext($element));
330336
var stateHash = createStateHash(stateName, stateParams);
331337

332-
states.push({
338+
var stateInfo = {
333339
state: state || { name: stateName },
334340
params: stateParams,
335341
hash: stateHash
336-
});
342+
};
337343

344+
states.push(stateInfo);
338345
activeClasses[stateHash] = activeClass;
346+
347+
return function removeState() {
348+
var idx = states.indexOf(stateInfo);
349+
if (idx !== -1) states.splice(idx, 1);
350+
};
339351
}
340352

341353
/**

test/stateDirectivesSpec.js

+36-3
Original file line numberDiff line numberDiff line change
@@ -292,10 +292,11 @@ describe('uiStateRef', function() {
292292
});
293293

294294
describe('links with dynamic state definitions', function () {
295-
var template;
295+
var template, $state;
296296

297-
beforeEach(inject(function($rootScope, $compile, $state) {
298-
el = angular.element('<a ui-state="state" ui-state-params="params">state</a>');
297+
beforeEach(inject(function($rootScope, $compile, _$state_) {
298+
$state = _$state_;
299+
el = angular.element('<a ui-sref-active="active" ui-sref-active-eq="activeeq" ui-state="state" ui-state-params="params">state</a>');
299300
scope = $rootScope;
300301
angular.extend(scope, { state: 'contacts', params: {} });
301302
template = $compile(el)(scope);
@@ -326,6 +327,38 @@ describe('uiStateRef', function() {
326327
expect(angular.element(template[0]).attr('href')).toBe('#/contacts');
327328
});
328329

330+
it('updates a linked ui-sref-active', inject(function ($timeout) {
331+
function tick() { scope.$digest(); try { $timeout.flush(); } catch (error) { } }
332+
expect(template[0].className).not.toContain('active');
333+
expect(template[0].className).not.toContain('activeeq');
334+
335+
$state.go('contacts');
336+
tick();
337+
expect(template[0].className).toContain('active activeeq');
338+
339+
scope.state = 'contacts.item';
340+
scope.params = { id: 5 };
341+
tick();
342+
expect(template[0].className).not.toContain('active');
343+
expect(template[0].className).not.toContain('activeeq');
344+
345+
$state.go('contacts.item', { id: -5 });
346+
tick();
347+
expect(template[0].className).not.toContain('active');
348+
expect(template[0].className).not.toContain('activeeq');
349+
350+
$state.go('contacts.item', { id: 5 });
351+
tick();
352+
expect(template[0].className).toContain('active activeeq');
353+
354+
scope.state = 'contacts';
355+
scope.params = { };
356+
tick();
357+
expect(template[0].className).toContain('active');
358+
expect(template[0].className).not.toContain('activeeq');
359+
360+
}));
361+
329362
it('accepts param overrides', inject(function ($compile) {
330363
el = angular.element('<a ui-state="state" ui-state-params="params">state</a>');
331364
scope.state = 'contacts.item';

0 commit comments

Comments
 (0)