diff --git a/src/ng1/stateDirectives.ts b/src/ng1/stateDirectives.ts
index 265d61cd4..298b3cfb1 100644
--- a/src/ng1/stateDirectives.ts
+++ b/src/ng1/stateDirectives.ts
@@ -179,12 +179,17 @@ function $StateRefDynamicDirective($state, $timeout) {
var group = [attrs.uiState, attrs.uiStateParams || null, attrs.uiStateOpts || null];
var watch = '[' + group.map(function(val) { return val || 'null'; }).join(', ') + ']';
var def = { state: null, params: null, options: null, href: null };
+ var unlinkInfoFn = null;
function runStateRefLink (group) {
def.state = group[0]; def.params = group[1]; def.options = group[2];
def.href = $state.href(def.state, def.params, def.options);
- if (active) active.$$addStateInfo(def.state, def.params);
+ if (unlinkInfoFn) {
+ unlinkInfoFn();
+ unlinkInfoFn = null;
+ }
+ if (active) unlinkInfoFn = active.$$addStateInfo(def.state, def.params);
if (def.href) attrs.$set(type.attr, def.href);
}
@@ -325,8 +330,9 @@ function $StateRefActiveDirective($state, $stateParams, $interpolate, $transitio
if (isObject(uiSrefActive) && states.length > 0) {
return;
}
- addState(newState, newParams, uiSrefActive);
+ var deregister = addState(newState, newParams, uiSrefActive);
update();
+ return deregister;
};
$scope.$on('$stateChangeSuccess', update);
@@ -338,13 +344,19 @@ function $StateRefActiveDirective($state, $stateParams, $interpolate, $transitio
var state = $state.get(stateName, stateContext($element));
var stateHash = createStateHash(stateName, stateParams);
- states.push({
+ var stateInfo = {
state: state || { name: stateName },
params: stateParams,
hash: stateHash
- });
+ };
+ states.push(stateInfo);
activeClasses[stateHash] = activeClass;
+
+ return function removeState() {
+ var idx = states.indexOf(stateInfo);
+ if (idx !== -1) states.splice(idx, 1);
+ }
}
/**
diff --git a/test/stateDirectivesSpec.js b/test/stateDirectivesSpec.js
index b4d2498d4..df1d3fa7b 100644
--- a/test/stateDirectivesSpec.js
+++ b/test/stateDirectivesSpec.js
@@ -302,10 +302,11 @@ describe('uiStateRef', function() {
});
describe('links with dynamic state definitions', function () {
- var template;
+ var template, $state;
- beforeEach(inject(function($rootScope, $compile, $state) {
- el = angular.element('state');
+ beforeEach(inject(function($rootScope, $compile, _$state_) {
+ $state = _$state_;
+ el = angular.element('state');
scope = $rootScope;
angular.extend(scope, { state: 'contacts', params: {} });
template = $compile(el)(scope);
@@ -329,6 +330,38 @@ describe('uiStateRef', function() {
expect(angular.element(template[0]).attr('href')).toBe('#/contacts/25');
});
+ it('updates a linked ui-sref-active', inject(function ($timeout) {
+ function tick() { scope.$digest(); try { $timeout.flush(); } catch (error) { } }
+ expect(template[0].className).not.toContain('active');
+ expect(template[0].className).not.toContain('activeeq');
+
+ $state.go('contacts');
+ tick();
+ expect(template[0].className).toContain('active activeeq');
+
+ scope.state = 'contacts.item';
+ scope.params = { id: 5 };
+ tick();
+ expect(template[0].className).not.toContain('active');
+ expect(template[0].className).not.toContain('activeeq');
+
+ $state.go('contacts.item', { id: -5 });
+ tick();
+ expect(template[0].className).not.toContain('active');
+ expect(template[0].className).not.toContain('activeeq');
+
+ $state.go('contacts.item', { id: 5 });
+ tick();
+ expect(template[0].className).toContain('active activeeq');
+
+ scope.state = 'contacts';
+ scope.params = { };
+ tick();
+ expect(template[0].className).toContain('active');
+ expect(template[0].className).not.toContain('activeeq');
+
+ }));
+
it('retains the old href if the new points to a non-state', function () {
expect(angular.element(template[0]).attr('href')).toBe('#/contacts');
scope.state = 'nostate';