Skip to content

Commit a36f1fb

Browse files
committed
fix(modal): Support close animation
Tests now have to wait for animation before checking for open modals. Tests should actually check for the 'in' class. Setting up both the transition end handler and a timeout ensures that the modal is always closed even if there was an issue with the transition. This was the implementation used by Twitter Bootstrap modal JS code. Note that unbinding the transition end event within the event handler isn't necessary, and, worse is currently buggy in jqLite (see angular/angular.js#5109 ). Note that the scope is already destroyed when the dom is removed so the $destroy call isn't needed. Closes angular-ui#1341
1 parent 0b39994 commit a36f1fb

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

Diff for: src/modal/modal.js

+29-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
angular.module('ui.bootstrap.modal', [])
1+
angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
22

33
/**
44
* A helper, internal data structure that acts as a map but also allows getting / removing
@@ -87,7 +87,8 @@ angular.module('ui.bootstrap.modal', [])
8787
return {
8888
restrict: 'EA',
8989
scope: {
90-
index: '@'
90+
index: '@',
91+
animate: '='
9192
},
9293
replace: true,
9394
transclude: true,
@@ -106,8 +107,8 @@ angular.module('ui.bootstrap.modal', [])
106107
};
107108
}])
108109

109-
.factory('$modalStack', ['$document', '$compile', '$rootScope', '$$stackedMap',
110-
function ($document, $compile, $rootScope, $$stackedMap) {
110+
.factory('$modalStack', ['$transition', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap',
111+
function ($transition, $timeout, $document, $compile, $rootScope, $$stackedMap) {
111112

112113
var OPENED_MODAL_CLASS = 'modal-open';
113114

@@ -140,17 +141,36 @@ angular.module('ui.bootstrap.modal', [])
140141
openedWindows.remove(modalInstance);
141142

142143
//remove window DOM element
143-
modalWindow.modalDomEl.remove();
144+
removeAfterAnimating(modalWindow.modalDomEl, modalWindow.modalScope);
144145
body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);
145146

146147
//remove backdrop if no longer needed
147148
if (backdropDomEl && backdropIndex() == -1) {
148-
backdropDomEl.remove();
149+
removeAfterAnimating(backdropDomEl, backdropScope);
149150
backdropDomEl = undefined;
150151
}
152+
}
151153

152-
//destroy scope
153-
modalWindow.modalScope.$destroy();
154+
function removeAfterAnimating(domEl, scope) {
155+
// Closing animation
156+
$timeout(function () {
157+
scope.animate = false;
158+
});
159+
160+
var transitionEndEventName = $transition.transitionEndEventName;
161+
if (transitionEndEventName) {
162+
// transition out
163+
var timeout = $timeout(function () {
164+
domEl.remove();
165+
}, 500);
166+
167+
domEl.bind(transitionEndEventName, function () {
168+
$timeout.cancel(timeout);
169+
domEl.remove();
170+
});
171+
} else {
172+
domEl.remove();
173+
}
154174
}
155175

156176
$document.bind('keydown', function (evt) {
@@ -186,6 +206,7 @@ angular.module('ui.bootstrap.modal', [])
186206
var angularDomEl = angular.element('<div modal-window></div>');
187207
angularDomEl.attr('window-class', modal.windowClass);
188208
angularDomEl.attr('index', openedWindows.length() - 1);
209+
angularDomEl.attr('animate', 'animate');
189210
angularDomEl.html(modal.content);
190211

191212
var modalDomEl = $compile(angularDomEl)(modal.scope);

Diff for: src/modal/test/modal.spec.js

+3
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ describe('$modal', function () {
104104

105105
function dismiss(modal, reason) {
106106
modal.dismiss(reason);
107+
$timeout.flush();
107108
$rootScope.$digest();
108109
}
109110

@@ -144,6 +145,7 @@ describe('$modal', function () {
144145
expect($document).toHaveModalsOpen(1);
145146

146147
triggerKeyDown($document, 27);
148+
$timeout.flush();
147149
$rootScope.$digest();
148150

149151
expect($document).toHaveModalsOpen(0);
@@ -155,6 +157,7 @@ describe('$modal', function () {
155157
expect($document).toHaveModalsOpen(1);
156158

157159
$document.find('body > div.modal-backdrop').click();
160+
$timeout.flush();
158161
$rootScope.$digest();
159162

160163
expect($document).toHaveModalsOpen(0);

0 commit comments

Comments
 (0)