AngularJs Run block $stateChangeStart not being fired - angularjs

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) {

Related

How to call a function in all controllers in AngularJs

I have a function validateSesion that i need to call every time a controller is executed.
There is a way to trigger the function without putting the call to the function in all the controllers?
The way I would recommend accomplishing such a call would be to create event handlers for your route changes. This way every time you change your route or state (if you are using ui-router) you can run your code.
You would place this in your app's run function and attach the event handlers to the $rootScope as shown below:
angular.module('app', [
//Your Dependencies Here
]).run(init);
function init($rootScope, sessionService) {
//ngRoute
$rootScope.$on('$routeChangeStart', function (angularEvent, next, current) {
sessionService.validateSession();
});
//ui-router
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
sessionService.validateSession();
});
}

Difficultly with $locationChangeStart and $stateChangeStart events in AngularJS

I'm having the classic problem where the $locationChangeStart event fires multiple times. I've tried to use the preventDefault but I can't seem to master this.
Two problems - first scenario uses $location and the second uses $state:
Once user is authenticated, I redirect using $state.go('main') , however $locationChangeStart is fired again. I do not want this behavior.
With the ui-router $stateChangeStart event, I basically hit an infinite loop scenario. Meaning that, when this event fires I check for user authentication. If the user is NOT authenticated, I then redirect using $state.go('login');. This causes an infinite loop.
Here's my app.js for starters:
(function () {
'use strict';
angular.module('rage', [
'ui.router',
'ui.bootstrap',
'ui.dashboard',
'kendo.directives'
]).run(['$rootScope', '$state', '$location', 'userService', 'loginService', init]);
function init($rootScope, $state, $location, userService, loginService) {
$rootScope.rageSessionVars = {};
$rootScope.$state = $state;
$rootScope.isLoggedin = false; // just something to possibly use ???
$rootScope.$on('$locationChangeStart', function () {
var userToken = loginService.getUserCookie();
// check if cookie expired, then authenticate user !
if (userToken) {
if (!loginService.isUserCookieExpired(userToken)) {
if (loginService.authUser(userToken)) {
$state.go('main');
}
else {
$location.url('index.html#/?login'); // not authenticated !
}
}
}
else {
$state.go('login');
$location.url('index.html#/?login');
}
});
}
})();
I've also created a plunker for a similar scenario yesterday, and simply modified the app.js to now include the locationChangeStart event.
Online plunker here: http://plnkr.co/edit/hsSrPqFp0hpJ4A8cTsVL?p=preview
Bottom line is I'd like to hook into one of these event for a smooth user Login/Logout experience, but I always end up in a snag with these Angular events.
Thank you in advance for your expert tips.
regards,
Bob
While using angular ui router, use $stateChangeStart and $stateChangeSuccess to control actions like authentications and manual routing during state changing.

Is there any event like OnRouteChange in angular?

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.

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);
});

Updating title tag using AngularJS and UI-Router

I am running into a weird issue while trying to set the title of the page using the name of the current state (via ui-router).
Actually, the issue is not with setting the title, the issue is that the title gets set to the title of the next state before the history.pushState. So when I transition to a new url, the first item in the history has the same name as the current page.
I was just playing around with the sample (http://angular-ui.github.io/ui-router/sample/) and I managed to reproduce it there as well. If you click on About, then back on home you will see 2 different entries for 'home'. They both point to the correct url, but their names are mangled. Weirdly enough, clicking through the Contact.list and contact.details sets the history properly.
Is there a way around this? When in the pipeline does the history.pushstate get called?
I had a 'similar' situation... and answered it here.
It basically defines $rootScope.$state = $state inside of the run method of angular. That allows us to access current states info in templates.
<title ng-bind="$state.current.data.pageTitle"></title>
The key is defining it on the $rootScope in the run method.
I have a similar situation like yours and I do it like the following.
You can put that in your main app run block like following.
I had
angular.module('myApp').run([
'$log', '$rootScope', '$window', '$state', '$location',
function($log, $rootScope, $window, $state, $location) {
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
if (toState.title) {
$rootScope.pageTitle = toState.title;
}
});
$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
// something else
});
$state.go('home');
}
]);
and in the html head i have
<html class="no-js" class="ng-app" ng-app="..." id="ng-app">
<head>
....
<title ng-bind="pageTitle"></title>
hope this works for you.
PS: Please consult https://docs.angularjs.org/guide/module for details.
I wrote the angular-ui-router-title plugin for this. You can use it to update the page title to a static or dynamic value based on the current state. It correctly works with browser history, too.

Resources