Skip to content
This repository was archived by the owner on May 29, 2019. It is now read-only.

Commit 3584061

Browse files
committed
fix(modal): dismiss modal on unschedule destruction
- Dismiss modal via `modalInstance.dismiss` if the `$scope` undergoes an unscheduled destruction Closes #4097 Fixes #3694
1 parent 5ae5be6 commit 3584061

File tree

3 files changed

+21
-0
lines changed

3 files changed

+21
-0
lines changed

src/modal/docs/readme.md

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ In addition the scope associated with modal's content is augmented with 2 method
3535

3636
Those methods make it easy to close a modal window without a need to create a dedicated controller.
3737

38+
If the $scope is destroyed via unexpected mechanism, such as it being passed in the modal options and a $route/$state transition occurs, the modal will be dismissed with the value `$uibModal`.
39+
3840
Finally, a `modal.closing` event is broadcast to the modal scope before the modal closes. If the listener calls
3941
preventDefault on the event, then the modal will remain open. The $close and $dismiss methods return true if the
4042
event was allowed. The event itself includes a parameter for the result/reason and a boolean parameter that indicates

src/modal/modal.js

+8
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ angular.module('ui.bootstrap.modal', [])
375375
$modalStack.close = function (modalInstance, result) {
376376
var modalWindow = openedWindows.get(modalInstance);
377377
if (modalWindow && broadcastClosing(modalWindow, result, true)) {
378+
modalWindow.value.modalScope.$$uibDestructionScheduled = true;
378379
modalWindow.value.deferred.resolve(result);
379380
removeModalWindow(modalInstance, modalWindow.value.modalOpener);
380381
return true;
@@ -385,6 +386,7 @@ angular.module('ui.bootstrap.modal', [])
385386
$modalStack.dismiss = function (modalInstance, reason) {
386387
var modalWindow = openedWindows.get(modalInstance);
387388
if (modalWindow && broadcastClosing(modalWindow, reason, false)) {
389+
modalWindow.value.modalScope.$$uibDestructionScheduled = true;
388390
modalWindow.value.deferred.reject(reason);
389391
removeModalWindow(modalInstance, modalWindow.value.modalOpener);
390392
return true;
@@ -524,6 +526,12 @@ angular.module('ui.bootstrap.modal', [])
524526
modalScope.$close = modalInstance.close;
525527
modalScope.$dismiss = modalInstance.dismiss;
526528

529+
modalScope.$on('$destroy', function() {
530+
if (!modalScope.$$uibDestructionScheduled) {
531+
modalScope.$dismiss('$uibModal');
532+
}
533+
});
534+
527535
var ctrlInstance, ctrlLocals = {};
528536
var resolveIter = 1;
529537

src/modal/test/modal.spec.js

+11
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,17 @@ describe('$modal', function () {
314314
expect(modal.result).toBeRejectedWith('esc');
315315
});
316316

317+
it('should reject returned promise on unexpected closure', function () {
318+
var scope = $rootScope.$new();
319+
var modal = open({template: '<div>Content</div>', scope: scope});
320+
scope.$destroy();
321+
322+
expect(modal.result).toBeRejectedWith('$uibModal');
323+
324+
$animate.triggerCallbacks();
325+
expect($document).toHaveModalsOpen(0);
326+
});
327+
317328
it('should expose a promise linked to the templateUrl / resolve promises', function () {
318329
var modal = open({template: '<div>Content</div>', resolve: {
319330
ok: function() {return $q.when('ok');}

0 commit comments

Comments
 (0)