From 0286828be3f95f88684e4e16bc47830f3bdaf6e0 Mon Sep 17 00:00:00 2001 From: Chris Chua Date: Sat, 4 Jul 2015 16:40:42 -0700 Subject: [PATCH] fix(modal): closing breaks on missing scope, 1.4 - supports Angular 1.4 Fixes #3787 Fixes #3806 Fixes #3873 Closes #3888 --- src/modal/modal.js | 49 +++++++++++++++++++++++++++++------- src/modal/test/modal.spec.js | 4 +-- template/modal/window.html | 3 ++- 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/modal/modal.js b/src/modal/modal.js index c2de63924b..ac64c03188 100644 --- a/src/modal/modal.js +++ b/src/modal/modal.js @@ -78,12 +78,13 @@ angular.module('ui.bootstrap.modal', []) } }]) - .directive('modalWindow', ['$modalStack', '$q', function ($modalStack, $q) { + .directive('modalWindow', [ + '$modalStack', '$q', '$animate', + function ($modalStack , $q , $animate) { return { restrict: 'EA', scope: { - index: '@', - animate: '=' + index: '@' }, replace: true, transclude: true, @@ -119,8 +120,14 @@ angular.module('ui.bootstrap.modal', []) }); modalRenderDeferObj.promise.then(function () { - // trigger CSS transitions - scope.animate = true; + if (attrs.modalInClass) { + $animate.addClass(element, attrs.modalInClass); + + scope.$on($modalStack.WINDOW_CLOSING_EVENT, function (e, setIsAsync) { + var done = setIsAsync(); + $animate.removeClass(element, attrs.modalInClass).then(done); + }); + } var inputsWithAutofocus = element[0].querySelectorAll('[autofocus]'); /** @@ -169,14 +176,21 @@ angular.module('ui.bootstrap.modal', []) }; }) - .factory('$modalStack', ['$animate', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap', - function ($animate, $timeout, $document, $compile, $rootScope, $$stackedMap) { + .factory('$modalStack', [ + '$animate', '$timeout', '$document', '$compile', '$rootScope', + '$q', + '$$stackedMap', + function ($animate , $timeout , $document , $compile , $rootScope , + $q, + $$stackedMap) { var OPENED_MODAL_CLASS = 'modal-open'; var backdropDomEl, backdropScope; var openedWindows = $$stackedMap.createNew(); - var $modalStack = {}; + var $modalStack = { + WINDOW_CLOSING_EVENT: 'modal.stack.window-closing' + }; function backdropIndex() { var topBackdropIndex = -1; @@ -203,8 +217,25 @@ angular.module('ui.bootstrap.modal', []) //clean up the stack openedWindows.remove(modalInstance); + var closingDeferred; + var closingPromise; + var setIsAsync = function () { + if (!closingDeferred) { + closingDeferred = $q.defer(); + closingPromise = closingDeferred.promise; + } + + return function () { + closingDeferred.resolve(); + }; + }; + modalWindow.modalScope.$broadcast($modalStack.WINDOW_CLOSING_EVENT, setIsAsync); + //remove window DOM element - removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() { + $q.when(closingPromise).then(function() { + modalWindow.modalDomEl.remove(); + modalWindow.modalScope.$destroy(); + body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0); checkRemoveBackdrop(); }); diff --git a/src/modal/test/modal.spec.js b/src/modal/test/modal.spec.js index 0afe94ab8d..c60c1f75f8 100644 --- a/src/modal/test/modal.spec.js +++ b/src/modal/test/modal.spec.js @@ -147,19 +147,19 @@ describe('$modal', function () { function close(modal, result, noFlush) { var closed = modal.close(result); + $rootScope.$digest(); if (!noFlush) { $timeout.flush(); } - $rootScope.$digest(); return closed; } function dismiss(modal, reason, noFlush) { var closed = modal.dismiss(reason); + $rootScope.$digest(); if (!noFlush) { $timeout.flush(); } - $rootScope.$digest(); return closed; } diff --git a/template/modal/window.html b/template/modal/window.html index 5501937bd6..0bb4f964b6 100644 --- a/template/modal/window.html +++ b/template/modal/window.html @@ -1,5 +1,6 @@