Is there a way to automatically close Angular UI Bootstrap modal when route changes?
Solution 1
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 :-)
Solution 2
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);
}
});
}]);
Solution 3
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.
Solution 4
I resolved this issue by doing something like this:
$rootScope.$on('$stateChangeSuccess',
function(event, toState, toParams, fromState, fromParams){
$modalStack.dismissAll();
});
Solution 5
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();
});
}]);
szimek
Updated on July 09, 2022Comments
-
szimek almost 2 years
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 oneng-click
per template to handle all links? -
szimek almost 10 yearsIt 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?
-
boatcoder almost 10 yearsChange the url when you click that button?
-
szimek almost 10 years@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.
-
boatcoder almost 10 yearsI'm saying change that behavior. Make the TOS page a new URL, voila!
-
Per Quested Aronsson over 9 yearsapp.run(function ($rootScope, $modalStack) { $rootScope.$on('$routeChangeSuccess', function (newVal, oldVal) { if (oldVal !== newVal) { $modalStack.dismissAll(); } }); });
-
chovy almost 8 years
Unknown provider: $uibModalStackProvider
-
Kiran Kumar over 7 yearsDo you know the solution for this in angular 2.
-
Leon Gaban over 7 yearsDo you have a link to the
uibModalStack
documentation? Can't find it anywhere... -
bits almost 5 yearsI 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.