Skip to content

Commit 1be1379

Browse files
author
Teemu Kokkonen
committed
fix(viewDirective): $destroy event is triggered before animation ends
when view is animated using ngAnimate, $destroy event is triggered before animation ends. closes #1643
1 parent d23e9fa commit 1be1379

File tree

2 files changed

+56
-9
lines changed

2 files changed

+56
-9
lines changed

src/viewDirective.js

+21-8
Original file line numberDiff line numberDiff line change
@@ -190,32 +190,45 @@ function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate)
190190
updateView(true);
191191

192192
function cleanupLastView() {
193-
if (previousEl) {
194-
previousEl.remove();
195-
previousEl = null;
193+
var _previousEl = previousEl;
194+
var _currentScope = currentScope;
195+
196+
if (_currentScope) {
197+
_currentScope._willBeDestroyed = true;
196198
}
197199

198-
if (currentScope) {
199-
currentScope.$destroy();
200-
currentScope = null;
200+
function cleanOld() {
201+
if (_previousEl) {
202+
_previousEl.remove();
203+
}
204+
205+
if (_currentScope) {
206+
_currentScope.$destroy();
207+
}
201208
}
202209

203210
if (currentEl) {
204211
renderer.leave(currentEl, function() {
212+
cleanOld();
205213
previousEl = null;
206214
});
207215

208216
previousEl = currentEl;
209-
currentEl = null;
217+
} else {
218+
cleanOld();
219+
previousEl = null;
210220
}
221+
222+
currentEl = null;
223+
currentScope = null;
211224
}
212225

213226
function updateView(firstTime) {
214227
var newScope,
215228
name = getUiViewName(scope, attrs, $element, $interpolate),
216229
previousLocals = name && $state.$current && $state.$current.locals[name];
217230

218-
if (!firstTime && previousLocals === latestLocals) return; // nothing to do
231+
if (!firstTime && previousLocals === latestLocals || scope._willBeDestroyed) return; // nothing to do
219232
newScope = scope.$new();
220233
latestLocals = $state.$current.locals[name];
221234

test/viewDirectiveSpec.js

+35-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
describe('uiView', function () {
55
'use strict';
66

7-
var scope, $compile, elem;
7+
var log, scope, $compile, elem;
88

99
beforeEach(function() {
1010
var depends = ['ui.router'];
@@ -27,6 +27,10 @@ describe('uiView', function () {
2727
});
2828
}));
2929

30+
beforeEach(function() {
31+
log = '';
32+
});
33+
3034
var aState = {
3135
template: 'aState template'
3236
},
@@ -112,6 +116,19 @@ describe('uiView', function () {
112116
.state('j', jState)
113117
.state('k', kState)
114118
.state('l', lState)
119+
.state('m', {
120+
controller: function($scope) {
121+
log += 'm;';
122+
$scope.$on('$destroy', function() {
123+
log += '$destroy(m);';
124+
});
125+
},
126+
})
127+
.state('n', {
128+
controller: function($scope) {
129+
log += 'n;';
130+
},
131+
});
115132
}));
116133

117134
beforeEach(inject(function ($rootScope, _$compile_) {
@@ -122,6 +139,23 @@ describe('uiView', function () {
122139

123140
describe('linking ui-directive', function () {
124141

142+
it('$destroy event is triggered after animation ends', inject(function($state, $q, $animate) {
143+
elem.append($compile('<div><ui-view></ui-view></div>')(scope));
144+
145+
$state.transitionTo('m');
146+
$q.flush();
147+
expect(log).toBe('m;');
148+
$state.transitionTo('n');
149+
$q.flush();
150+
if ($animate) {
151+
expect(log).toBe('m;n;');
152+
$animate.triggerCallbacks();
153+
expect(log).toBe('m;n;$destroy(m);');
154+
} else {
155+
expect(log).toBe('m;$destroy(m);n;');
156+
}
157+
}));
158+
125159
it('anonymous ui-view should be replaced with the template of the current $state', inject(function ($state, $q) {
126160
elem.append($compile('<div><ui-view></ui-view></div>')(scope));
127161

0 commit comments

Comments
 (0)