I've got links in templates inside modals. When I click them, the current page changes, but the overlay and modal stay. I could add ng-click="dimiss()"
to every link in all templates in modals, but is there a better way? E.g. to close it automatically on successful route change or add just one ng-click
per template to handle all links?

- 6,404
- 5
- 32
- 36
7 Answers
If you want all the opened modals to be closed whenever a route is changed successfully, you could do it in one central place by listening to the $routeChangeSuccess
event, for example in a run block of your app:
var myApp = angular.module('app', []).run(function($rootScope, $uibModalStack) {
$uibModalStack.dismissAll();
});
Here you can see that the $uibModalStack
service gets injected on which you can call the dismissAll
method - this call will close all the currently opened modals.
So, yes, you can handle modals closing centrally, in one place, with one line of code :-)

- 6,443
- 2
- 38
- 59

- 117,202
- 60
- 326
- 286
-
It works almost fine :) I've got "sign in" modal with a link to "terms of service" page. The button to open this modal is in the header bar that is always visible, so it's possible to open this modal on "terms of service" page as well. When I click this link while I'm on "terms of service" page, the route doesn't change and success event is not fired. Any idea how to solve it? Is there any event fired in such case that I could listen to? – szimek May 21 '14 at 07:39
-
Change the url when you click that button? – boatcoder Jul 04 '14 at 11:02
-
@Mark0978 The issue is that you're on the same page to which the link inside the modal points to, so there's no URL change. – szimek Jul 04 '14 at 14:19
-
I'm saying change that behavior. Make the TOS page a new URL, voila! – boatcoder Jul 04 '14 at 15:15
-
13app.run(function ($rootScope, $modalStack) { $rootScope.$on('$routeChangeSuccess', function (newVal, oldVal) { if (oldVal !== newVal) { $modalStack.dismissAll(); } }); }); – Per Quested Aronsson Oct 30 '14 at 09:13
-
2`Unknown provider: $uibModalStackProvider` – chovy May 04 '16 at 21:20
-
1Do you know the solution for this in angular 2. – Kiran Kumar Nov 06 '16 at 19:07
-
6Do you have a link to the `uibModalStack` documentation? Can't find it anywhere... – Leon Gaban Dec 26 '16 at 17:21
A better way is to see that whenever a Popup (Modal) is open, on Browser Back button click (or Keyboard Back), we stop the URL change and just close the Popup. This works for a better User Experience in my Project.
The Browser Back button works normally if there is no Modal opened.
use:
$uibModalStack.dismiss(openedModal.key);
or
$uibModalStack.dismissAll;
Sample code:
.run(['$rootScope', '$uibModalStack',
function ($rootScope, $uibModalStack) {
// close the opened modal on location change.
$rootScope.$on('$locationChangeStart', function ($event) {
var openedModal = $uibModalStack.getTop();
if (openedModal) {
if (!!$event.preventDefault) {
$event.preventDefault();
}
if (!!$event.stopPropagation) {
$event.stopPropagation();
}
$uibModalStack.dismiss(openedModal.key);
}
});
}]);

- 160
- 1
- 6
-
I used this code, but this conflicts with uirouter. When I have a model with a button which initialises a state change, the modal is closed, the state is changed, BUT the URL isn't changed to the state's URL. This is because of the code above. I'm still looking for a solution. If I have it, I will post it here. – bits May 12 '19 at 10:33
I don't actually use Angular UI Bootstrap, but from looking at the docs, it looks like there is a close()
method on the $modalInstance
object.
So taking the example from the docs, this should work:
var ModalInstanceCtrl = function ($scope, $modalInstance, items) {
$scope.items = items;
$scope.selected = {
item: $scope.items[0]
};
$scope.ok = function () {
$modalInstance.close($scope.selected.item);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
// this will listen for route changes and call the callback
$scope.$on('$routeChangeStart', function(){
$modalInstance.close();
});
};
Hope that helps.

- 14,165
- 9
- 50
- 48
I resolved this issue by doing something like this:
$rootScope.$on('$stateChangeSuccess',
function(event, toState, toParams, fromState, fromParams){
$modalStack.dismissAll();
});

- 7,137
- 2
- 15
- 11
I am keeping this logic in the modal controller. You can listen to $locationChangeStart
event and close modal there. It is also good to remove listener after, especially if you have registered a listener on $rootScope
:
angular.module('MainApp').controller('ModalCtrl',['$scope','$uibModalInstance',
function ($scope, $uibModalInstance) {
var dismissModalListener = $scope.$on('$locationChangeStart', function () {
$uibModalInstance.close();
});
$scope.$on('$destroy', function() {
dismissModalListener();
});
}]);

- 1,198
- 13
- 15
check for the respective route condition in the event $stateChangeSuccess
and
then close the open bootstrap modals globally using the class like this:
$rootScope.$on('$stateChangeSuccess',
function(event, toState, toParams, fromState, fromParams){
//hide any open bootstrap modals
angular.element('.inmodal').hide();
});
If you want to hide any other modals such as angular material dialog ($mdDialog
) & sweet alert dialog's use angular.element('.modal-dialog').hide();
& angular.element('.sweet-alert').hide();

- 6,243
- 10
- 52
- 77
Adding this an alternative answer.
Depending on your project, using $uibModalStack.dismissAll()
could trigger an error message.
As explained by JB Nizet in this answer, it is caused by dismissAll()
rejecting a promise, leading to a 'failure' callback as opposed to a 'success' callback triggered by close()
.
Said promise rejection could trigger a possibly unwanted error handling procedure.
Given there is no closeAll()
in $uibModalStack
, I used this:
var modal = $uibModalStack.getTop();
while (modal && this.close(modal.key)) {
modal = this.getTop();
}
This is the same behaivour as $uibModalStack.dismissAll()
but utilizes.close()
instead of .dismiss()
.
I couldn't find any documentation describing public methods for $uibModalStack
, thus, in case anybody is interested in using/looking at other methods available on $uibModalStack
.
It'll likely be located in \node-modules\angular-ui-boostrap\dist\ui-boostrap-tpls.js
and dismissAll()
is @ line 4349
Took me a while to find it.

- 193
- 3
- 12