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

fix(modal): dismiss modal on unschedule destruction #4097

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/modal/docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ In addition the scope associated with modal's content is augmented with 2 method

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

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`.

Finally, a `modal.closing` event is broadcast to the modal scope before the modal closes. If the listener calls
preventDefault on the event, then the modal will remain open. The $close and $dismiss methods return true if the
event was allowed. The event itself includes a parameter for the result/reason and a boolean parameter that indicates
Expand Down
8 changes: 8 additions & 0 deletions src/modal/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ angular.module('ui.bootstrap.modal', [])
$modalStack.close = function (modalInstance, result) {
var modalWindow = openedWindows.get(modalInstance);
if (modalWindow && broadcastClosing(modalWindow, result, true)) {
modalWindow.value.modalScope.$$uibDestructionScheduled = true;
modalWindow.value.deferred.resolve(result);
removeModalWindow(modalInstance, modalWindow.value.modalOpener);
return true;
Expand All @@ -385,6 +386,7 @@ angular.module('ui.bootstrap.modal', [])
$modalStack.dismiss = function (modalInstance, reason) {
var modalWindow = openedWindows.get(modalInstance);
if (modalWindow && broadcastClosing(modalWindow, reason, false)) {
modalWindow.value.modalScope.$$uibDestructionScheduled = true;
modalWindow.value.deferred.reject(reason);
removeModalWindow(modalInstance, modalWindow.value.modalOpener);
return true;
Expand Down Expand Up @@ -524,6 +526,12 @@ angular.module('ui.bootstrap.modal', [])
modalScope.$close = modalInstance.close;
modalScope.$dismiss = modalInstance.dismiss;

modalScope.$on('$destroy', function() {
if (!modalScope.$$uibDestructionScheduled) {
modalScope.$dismiss('$uibModal');
}
});

var ctrlInstance, ctrlLocals = {};
var resolveIter = 1;

Expand Down
11 changes: 11 additions & 0 deletions src/modal/test/modal.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,17 @@ describe('$modal', function () {
expect(modal.result).toBeRejectedWith('esc');
});

it('should reject returned promise on unexpected closure', function () {
var scope = $rootScope.$new();
var modal = open({template: '<div>Content</div>', scope: scope});
scope.$destroy();

expect(modal.result).toBeRejectedWith('$uibModal');

$animate.triggerCallbacks();
expect($document).toHaveModalsOpen(0);
});

it('should expose a promise linked to the templateUrl / resolve promises', function () {
var modal = open({template: '<div>Content</div>', resolve: {
ok: function() {return $q.when('ok');}
Expand Down