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

Commit

Permalink
fix(modal): dismiss modal on unschedule destruction
Browse files Browse the repository at this point in the history
- Dismiss modal via `modalInstance.dismiss` if the `$scope` undergoes an unscheduled destruction

Closes #4097
Fixes #3694
  • Loading branch information
wesleycho committed Aug 4, 2015
1 parent 5ae5be6 commit 3584061
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 0 deletions.
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

0 comments on commit 3584061

Please sign in to comment.