I want to run a function on each route changes in angular.
Is there any event like OnRouteChange in angular?
yes there are some events like,
$routeChangeStart, $routeChangeSuccess, $routeChangeError, $routeUpdate
$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.
for EX:
app.run(function($rootScope, $location) {
$rootScope.$on('$routeChangeStart', function(event, next, current) {
});
$rootScope.$on('$routeChangeSuccess', function () {
});
$rootScope.$on('$routeChangeError', function () {
});
})
here is the DOC
here is a good article.
Related
My AngularJs run block does not execute the handler function when the application changes routes, at least that is what I think. I tried putting a simple console log to test and it does not log anything. The final objective is to be a route interceptor checking if the route needs authentication.
Link for github repository https://github.com/guilinden/authenticatedCRUD
(function(){
angular
.module('app')
.run(function ($rootScope, $location) {
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
var requireLogin = toState.data.requireLogin;
if(requireLogin){
event.preventDefault();
$location.path('/home');
}
});
});
})();
$stateChange* events are deprecated
The $stateChange* events are deprecated in 1.0. They are replaced with the $transitions.on* transition hooks.
However, they can be re-enabled for backwards compatibility by including stateEvents.js and depending on the 'ui.router.state.events' angular module.
<script src="stateEvents.js">
var myApp = angular.module('myApp', ['ui.router', 'ui.router.state.events']);
See UI-router Issue #2720 - $stateChangeStart not being fired on v1.0
There should be a app not defined error in your console. You are missing empty dependencies
angular
.module('app',[])
also change it as, $location as a dependency to run,
.run(function ($rootScope,$location) {
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
$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]);
}
});
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);
});
I have a controller that has an event called changeSafe. I want other controllers to listen when this event gets fired
secure.controller('wrapperCtrl', function ($scope, $rootScope, storeFactory, safeFactory) {
$scope.changeSafe = function (safeId) {
$scope.loading = true;
safeFactory.setSafe(safeId).then(function (safeData) {
$scope.safe = safeData;
$scope.loading = false;
$rootScope.$broadcast('changeSafe', safeData);
});
}
});
The first page that loads is called dashboard when I add what is below the page re-draws with $scope.safe as I would expect it to.
secure.controller('dashboardCtrl', function ($scope, $rootScope, storeFactory, safeFactory) {
$scope.$on('changeSafe', function (event, arg) {
bindSafe(arg.safeId);
});
});
I have pretty much the exact same thing on my history Controller
secure.controller('historyCtrl', function($scope, $rootScope, storeFactory, safeFactory) {
$scope.$on('changeSafe', function (event, arg) {
bindHistory(arg.safeId);
});
});
Here is I have in the config section
secure.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/history', {
templateUrl: '/Angular/History/history.html',
controller: 'historyCtrl'
})
.otherwise({
templateUrl: '/Angular/Dashboard/dashboard.html',
controller: 'dashboardCtrl'
});
}]);
Whenever I click the button that is held within wrapperCtrl only the $scope.$on fires in the dashboardCtrl. Can anyone see why the $scope.$on is not being fired from the historyCtrl controller? I'm also unclear why it gets called from dashboardCtrl when I'm not on that view anymore.
When I step through the code, I'm actually seeing the $rootScope.$on('changeSafe') getting called multiple times both on history page and dashboard page. I can't figure out why it is changing views back to the dashboard though
I'm not sure if I have a full grasp of your problem, but my best guess is you are having a load order issue and the event is being broadcasted before the subscription has been initialized.
First off, to save yourself a lot of headaches, it is important to have a solid understanding of Event Handling in AnguarJS:
know the difference between subscribing on $rootScope.$on vs
$scope.$on
know the difference of publishing with $broadcast vs $emit on
$rootScope vs $scope
From the comments it sounds like you might have been using $rootScope.$on, which isn't cleaned up when your controllers are destroyed (same as directives):
var changeSafeListnerUnbindFunction = $rootScope.$on('changeSafe', funciton() { //... });
$scope.$on('$destroy', changeSafeListnerUnbindFunction);
Given your use case, registering listeners on the child scopes will pick up events published from the $rootScope.$broadcast (which communicates top level down to each child scope).
You probably have a load order issue?
On first page load when app gets initialized I want to redirect the user to login page. I think the relevant part of the code is this
$rootScope.$on("$routeChangeStart", function (event, next, current) {
alert("change location");
$location.path('/login');
});
It is based on https://github.com/fnakstad/angular-client-side-auth/blob/master/app/js/app.js The problem is on page load the alert is triggered but location does not change. I have to click on a navigation item of my app and then the login action will be called and the route changes.
.run(['$rootScope', '$location', '$cookieStore', function ($rootScope,
$location, $cookieStore) {
$location.path('/login');
$rootScope.$on("$routeChangeStart", function (event, next, current) {
$location.path('/login');
});
$rootScope.appInitialized = true;
}]);
This will work however seems redundant. And why is alert triggered but not location change?
Why does the location not changes on full page load? How to fix this?
Full code http://jsfiddle.net/qfSC3/ but fiddle does not work.
Try using the $locationChangeStart event instead
$scope.$on("$locationChangeStart", function(event){
event.preventDefault();
})
Based off this question: AngularJS - Detecting, stalling, and cancelling route changes