From 1be13795686ab78abb2d5094bc8addcacb928975 Mon Sep 17 00:00:00 2001 From: Teemu Kokkonen Date: Fri, 30 Oct 2015 13:48:14 +0200 Subject: [PATCH] fix(viewDirective): $destroy event is triggered before animation ends when view is animated using ngAnimate, $destroy event is triggered before animation ends. closes #1643 --- src/viewDirective.js | 29 +++++++++++++++++++++-------- test/viewDirectiveSpec.js | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/viewDirective.js b/src/viewDirective.js index c55657b26..6661c078c 100644 --- a/src/viewDirective.js +++ b/src/viewDirective.js @@ -190,24 +190,37 @@ function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate) updateView(true); function cleanupLastView() { - if (previousEl) { - previousEl.remove(); - previousEl = null; + var _previousEl = previousEl; + var _currentScope = currentScope; + + if (_currentScope) { + _currentScope._willBeDestroyed = true; } - if (currentScope) { - currentScope.$destroy(); - currentScope = null; + function cleanOld() { + if (_previousEl) { + _previousEl.remove(); + } + + if (_currentScope) { + _currentScope.$destroy(); + } } if (currentEl) { renderer.leave(currentEl, function() { + cleanOld(); previousEl = null; }); previousEl = currentEl; - currentEl = null; + } else { + cleanOld(); + previousEl = null; } + + currentEl = null; + currentScope = null; } function updateView(firstTime) { @@ -215,7 +228,7 @@ function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate) name = getUiViewName(scope, attrs, $element, $interpolate), previousLocals = name && $state.$current && $state.$current.locals[name]; - if (!firstTime && previousLocals === latestLocals) return; // nothing to do + if (!firstTime && previousLocals === latestLocals || scope._willBeDestroyed) return; // nothing to do newScope = scope.$new(); latestLocals = $state.$current.locals[name]; diff --git a/test/viewDirectiveSpec.js b/test/viewDirectiveSpec.js index 44508b610..4ef370b16 100644 --- a/test/viewDirectiveSpec.js +++ b/test/viewDirectiveSpec.js @@ -4,7 +4,7 @@ describe('uiView', function () { 'use strict'; - var scope, $compile, elem; + var log, scope, $compile, elem; beforeEach(function() { var depends = ['ui.router']; @@ -27,6 +27,10 @@ describe('uiView', function () { }); })); + beforeEach(function() { + log = ''; + }); + var aState = { template: 'aState template' }, @@ -112,6 +116,19 @@ describe('uiView', function () { .state('j', jState) .state('k', kState) .state('l', lState) + .state('m', { + controller: function($scope) { + log += 'm;'; + $scope.$on('$destroy', function() { + log += '$destroy(m);'; + }); + }, + }) + .state('n', { + controller: function($scope) { + log += 'n;'; + }, + }); })); beforeEach(inject(function ($rootScope, _$compile_) { @@ -122,6 +139,23 @@ describe('uiView', function () { describe('linking ui-directive', function () { + it('$destroy event is triggered after animation ends', inject(function($state, $q, $animate) { + elem.append($compile('
')(scope)); + + $state.transitionTo('m'); + $q.flush(); + expect(log).toBe('m;'); + $state.transitionTo('n'); + $q.flush(); + if ($animate) { + expect(log).toBe('m;n;'); + $animate.triggerCallbacks(); + expect(log).toBe('m;n;$destroy(m);'); + } else { + expect(log).toBe('m;$destroy(m);n;'); + } + })); + it('anonymous ui-view should be replaced with the template of the current $state', inject(function ($state, $q) { elem.append($compile('
')(scope));