Order of routeChangeStart event and rendering - angularjs

I have a run function for a module and inside it there is a $routeChangeStart event binding. I would like to know time of the first routeChangeStart event triggered. I am expecting that it should be called immediately after first request but before any page render but it is not as I expected. It seems that the event is called after page started to be rendered.
module.run(function ($location, $rootScope) {
$rootScope.$on("$routeChangeStart", function (event, next, current) {
//do something with next.xxx
});
})
What is the expected behaviour? Or this is a bug?

The event is fired before the page starts rendering, but that doesn't mean you'll catch it before the rendering begins. The event gets fired, then the next thing in the call stack is when Angular begins the page rendering (fetching the template, waiting for the route resolve property, etc) and you catch the event after that. From the angular docs...
Broadcasted before a route change. At this point the route services
starts resolving all of the dependencies needed for the route change
to occur. Typically this involves fetching the view template as well
as any dependencies defined in resolve route property. Once all of the
dependencies are resolved $routeChangeSuccess is fired.
If you need to do something like conditionally preventing the change, try using the $locationChangeStart event instead. For example...
$scope.$on('$locationChangeStart', function (event) {
if (someCondition) {
event.preventDefault(); // prevent the change
}
});
This will be run before Angular starts loading the new page.

Related

AngularJS : prevent location change on back button or move cursor

Want to prevent from reload or move back to history urls
stop back button from browser on particular component
Note : only for angularJS not Angular(2..12)
Please import required directive in function definition "$rootScope"
$rootScope.$on('$locationChangeStart', function (event, newUrl, oldUrl) {
event.preventDefault(); // This prevents the navigation from happening
});
You can put above code in controller definition or can apply with watchers as well
Also instead of rootscope can be applied on scope only.
Ref : https://www.markcampbell.me/tutorial/2013/10/08/preventing-navigation-in-an-angularjs-project.html

How can I call an Angular function on each page view?

Right now I am using angular.element(document).ready(init()); but it calls init(); on every page refresh and not when browsing back and forth to the page. How could I call this function on every page view ?
I've tried also onload and ng-init and they don't work - the function doesn't get called.
I think this is what you're looking for:
$routeChangeSuccess Broadcasted after a route change has happened successfully. The resolve dependencies are now available in the
current.locals property.
ngView listens for the directive to instantiate the controller and
render the view.
This is what I do and it works for me:
$scope.$on('$routeChangeSuccess', function () {
// do something
});
Unless you're using ui-router. Then it's:
$scope.$on('$stateChangeSuccess', function () {
// do something
});
More info is found in the docs

$destroy event not working in angular

$scope.$on('$destroy', function (event){
$timeout.cancel(promiseObj);
});
If i am on a page that is being loaded(since the page contain $http request, it takes time to load data) and while loading, I change the page from navigation, the $timeout is not being deleted, and continuous http call are going. can you help?
Use $routeChangeStart instead of $destroy
$routeChangeStart
Broadcasted before a route change. At this point the route services starts resolving all of the dependencies needed for the route change to occur. Typically this involves fetching the view template as well as any dependencies defined in resolve route property. Once all of the dependencies are resolved $routeChangeSuccess is fired.
The route change (and the $location change that triggered it) can be prevented by calling preventDefault method of the event. See $rootScope.Scope for more details about event object.
So please try this below code.
$scope.$on('$routeChangeStart', function (scope, next, current) {
if (next.$$route.controller != "Your Controller Name") {
$timeout.cancel(promiseObj);// clear interval here
}
});
Actually, problem was angular created many objects with same name as promiseObj.
So, those object were not being deleted. So, I created an array of promiseObj[], and using for loop i deleted all the promises. ;)
$scope.$on('$destroy', function () {
for(var promise in promiseObj)
{
$timeout.cancel(promiseObj[promise]);
}
});

How to prevent route changing?

I have a service in which inside I bind a click event:
$('button').click(function() {
alert('Clicked');
return false;
});
The issue is when I do not start at the default "/" route (i.e. "/testroute"), then that same button when clicked, causes the page url to go to "/" and not fire my event at all. When I click on it again after the route changes to "/", the event triggers as normal. How do I make it such that if I were to start at /testroute (even though it has the same view, different controller, but shares the same service, the alert will fire?
Use locationChangeStart. Also read the link Andrey posted.
$rootScope.$on('$locationChangeStart', function(e) {
e.preventDefault();
});
You might want to use these events to prevent route changing.

Equivalence of window.onbeforeunload in AngularJS for routes

Regular JavaScript has window.onbeforeunload. How do I emulate the same in AngularJS with HTML5 routes?
There is $beforeRouteChange, but it doesn't allow you to cancel the event as far as I can tell.
To clarify: window.onbeforeunload would work for navigating away from the page, but not for intra page navigation, e.g. going from one controller to another just through the HTML5 history API.
Add this :
$scope.$on('$destroy', function() {
window.onbeforeunload = undefined;
});
$scope.$on('$locationChangeStart', function(event, next, current) {
if(!confirm("Are you sure you want to leave this page?")) {
event.preventDefault();
}
});
There is a $locationChangeStart event which can be canceled.
Since it hasn't been documented yet, here is the unit test describing how it affects the $route service.
https://github.com/angular/angular.js/blob/v1.0.1/test/ng/routeSpec.js#L63
This doesn't provide a confirmation for the user like window.onbeforeunload does. You need to bring your own dialog service and restart the location change process to get the same effect (or you could just use the synchronous $window.confirm).
If you are using angular-ui-router you need to use $stateChangeStart instead of $locationChangeStart.
When using UI-Router version 1.0.0+, use $transitions.onStart instead of $stateChangeStart. See the transition hooks documentation.
The $stateChange* events are deprecated as of version 1.0.0 (source):
All state events, (i.e. $stateChange* and friends) are now deprecated
and disabled by default. Instead of listening for events, use the
Transition Hook API.
Example code to abort a transition (source):
$transitions.onStart({}, function(transition) {
if (transition.to().name === 'unreachable') {
return false;
}
}

Resources