Closing a modal automatically on navigation (when clicking an anchor) - angularjs

I'm using angular-ui modal in my webapp. one of models display many links (anchor elements) that navigate to various parts of the app. the modal can be closed as usual with modal.dismiss() or modal.close(). but I need it to close when someone navigate out of it with clicking an anchor? usually (not angular) I could just attach an event to all the anchor clicks and close the modal from there. but in angular It seems somewhat complicated and not very "angularish" - Any ideas/directions on how to implement this?
e.g: I'm using angular-ui-router so if this can be solved through the routes It would also solve my problem.
Thanks!

Angular-ui-router fires events when a state change has occurred, so in your controller you could do something like:
$scope.currentModal = undefined;
// whenever a modal opens, ensure it is assigned to the $scope.currentModal. Not clear how
// you are managing your modals at the moment.
// this event-listener closes the current modal (if any)
$scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams){
if ($scope.currentModal) {
$scope.currentModal.dismiss();
}
})

Use $modalStack.dismissAll() to close any modalbox when state changes.
angular.module('myApp').controller('AppCtrl', ['$scope', '$rootScope', '$modal', '$modalStack',
function ($scope, $rootScope, $modal, $modalStack) {
$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams, options){
$modalStack.dismissAll();
});
}
]);

Related

Angularjs - stop loading application

I would like to ask how to stop loading application. I need this for showing modal window with login form. My idea is:
User go to my webpage, first start LoginController which check if user is authenticated. If not, it displays the form but must be stopped loading next controllers and components (loading data by user id).
Here is my concept:
<body ng-controller="LoginController">
controllers, components...
</body>
app.controller("LoginController", function LoginController(){
this.$onInit = function(){
if(!authenticated()){
showLoginModal();
stopLoadingApp(); // what will be implementation?
}
}
})
I tried this, but not called:
app.controller("LoginController", function LoginController($rootScope){
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
event.preventDefault(); //not called
});
});
Please help me how to solve this problem. Thanks

AngularJS routeChangeStart not working when on homepage

I can capture the Back Button in an AngularJs app using the $locationChangeStart event, so I can close a modal.
This works when I navigate away from the first page and then click a modal, then click back, I capture the Back event and close the modal and prevent the browser back default.
The problem is it does not work when on the homepage, none of the events get fired so I can't prevent default and close the modal, it just goes back to the new tab page (google)
$rootScope.$on("$locationChangeStart", function (event, next, current) {
event.preventDefault();
console.log('$locationChangeStart 1 ');
});
$rootScope.$on('$routeChangeStart', function (scope, next, current) {
event.preventDefault();
console.log('$routeChangeStart');
});
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
event.preventDefault();
console.log('$stateChangeStart');
});
$rootScope.$on('$destroy', function (event, next, current) {
event.preventDefault();
console.log('$locationChangeStart');
});
I'm using $routeProvider and don't really want to have to re-write it in ui-router.
Is there some config I have missed to get these events to fire when on my first page? or is there a hack?
thanks

AngularJS UI-Router event when changing route

Using ngRoute once can hook up in event: $routeChangeStart and do different actions ...
app.run(function ($rootScope, $location) {
$rootScope.$on("$routeChangeStart", function (event, next, current) {
................
Is it possible to achieve the same using UI-Router?
Yes it's possible:
$rootScope.$on("$stateChangeStart",
function (event, toState, toParams, fromState, fromParams) {
Or just use
$scope.$on("$stateChangeStart",...);
If you want this to be triggered on a single page.
Check this answer here, that's the correct way to fix it. Removing all listeners could have unknown effects as there might be other places where listeners are added. You need to remove the one you added, not all of them.
Check this issue: Angular $rootScope $on listeners in 'destroyed' controller keep running
Copying code here for completeness too:
animateApp.controller('mainController', function($scope, $rootScope, service) {
$scope.pageClass = 'page-home';
var unregister = $rootScope.$on('service.abc', function (newval) {
console.log($scope.$id);
});
$scope.$on('$destroy', unregister);
});

How can I bring up an "in progress" loading bar in between ui-router state transitions?

I have an AngularJS application that uses ui-router. There are times when the application waits while moving from one state to another and while the resolves are still in progress.
Does anyone have (or have they seen) any examples of how I can present an "in-progress" loading bar on the screen just during the time of the resolve from the one state to another?
You can use the events emitted by ui-router (as well as the native routeProvider).
Plunker
Something like this:
$rootScope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams){
$rootScope.stateIsLoading = true;
})
$rootScope.$on('$stateChangeSuccess',
function(event, toState, toParams, fromState, fromParams){
$rootScope.stateIsLoading = false;
})
Then in HTML:
<section ui-view ng-hide="stateIsLoading"></section>
<div class="loader" ng-show="stateIsLoading"></div>
docs
You can use resolve to provide your controller with content or data
that is custom to the state. resolve is an optional map of
dependencies which should be injected into the controller.
If any of these dependencies are promises, they will be resolved and
converted to a value before the controller is instantiated and the
$stateChangeSuccess event is fired.

Can't get $anchorScroll working on $stateChangeSuccess?

I'm trying to adapt the answer give in this similar question How to handle anchor hash linking in AngularJS. I need to be able to use it with ui-router. I've tested anchor scrolling as a clickable function in my controller and that is working. Here is the code for that
$scope.anchor = function () {
console.log('test');
$location.hash('comments');
$anchorScroll();
};
If I try to invoke that function immediately nothing happens
$scope.anchor();
If I try to invoke it on a $stateChangeSuccess nothing happens. I threw in a log for sanity and that is firing. I also tried a trick to prevent further routing logic from kicking in. It was mentioned in the linked post but I'm not sure if it's necessary for my case.
app.run(function ($rootScope, $location, $stateParams, $anchorScroll) {
// allow anchorScrolling
$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) {
console.log('stateChangeSuccess');
var old = $location.hash();
$location.hash('comments');
$anchorScroll();
//reset to old to keep any additional routing logic from kicking in
$location.hash(old);
});
});
I'm guessing that I'm running into race conditions or my anchor scroll is somehow triggering another route change. But I can't figure out how to track these issues down. Any thoughts?
EDIT: Update I removed the $location.hash(old); and put the rest of the $anchorScroll pieces into a timeout function and it's now working. I also added in the $stateParams.scrollTo to make this useable with query params. Any ideas as to what is causing my race condition and how this might be solved without a $timeout function?
$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) {
console.log('stateChangeSuccess');
$timeout(function() {
$location.hash($stateParams.scrollTo);
$anchorScroll();
}, 300);
});
From $anchorScroll documentation
It also watches the $location.hash() and scrolls whenever it changes to match any anchor. This can be disabled by calling $anchorScrollProvider.disableAutoScrolling().
Try removing $location.hash(old);
If that fixes it, use $anchorScrollProvider.disableAutoScrolling() to disable it reacting to another state change.

Resources