Redirect when app is initialized in angularjs - angularjs

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

Related

How can i redirect to another page without loading the current page in angularjs

I want to redirect to another page without loading the currentpage.
let me explain my task. I am having user login condition.
If the user has not login and he tries to enter the URL directly EX("localhost/sample.html") means it will come to login page. For me this condition is working nicely.
First sample.html page open and then only it will redirect to login. The user able to see the Data in sample.html.
var logincheck = function () {
debugger;
$http.get('loggedin').success(function (user) {
alert(user);
// Authenticated
if (user != '0') {
refresh();
return;
}
// Not Authenticated
else {
$window.location.href = '/';
}
});
};
logincheck();
Is there any way to go login page without loading the sample.html page.
A interesting way do to this is by checking this condition in a $route event. For example, you can write this code in your app.run:
$rootScope.$on('$routeChangeStart', function(event, next, current) {
if(next.$$route && userNotAuthenticated) {
$location.href('/');
}
});
The advantage is that it will work for your whole app, you won't have to write code for each page.
In your main controller (the one attached to index) you should do a login check and set a variable to true/false. In your controller do a check on this variable, and do a $state.go() if user is not logged in.
Use ng-cloak directive in your index file where you attach your main controller like:
<body ng-controller="mainController" ng-cloak>
You can read up on ng-cloak here
This is how you can do it.
Whenever your angular app is boots, it runs the run function. So attach a location change listener in that function like below
App.run(['$rootScope', '$http', '$urlRouter', function($rootScope, $http, $urlRouter) {
$rootScope.$on('$locationChangeSuccess', function(event) {
event.preventDefault();// prevents the location change
$http({// make a http call to check if user is logged in or not.
url: '/path/to/check/auth',
method: 'post',
data: {}
}).then(function(response){
if(response.data.isUserLoggedIn){//If user is logged in.
$urlRouter.sync();
}else{//user is not logged in
window.location.assign('/login');
}
}, function() {
window.location.assign('/login');
});
});
$urlRouter.listen();
}]);

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.

Forward to a specific page after logging in

I have an Angular app in which a user is redirected to the login page if they try to access a page for which they need to be authenticated. Currently, when the user is successfully authenticated from the login page, they are redirected to a default start page. The change that I need to make is this:
When a user is attempting to browse to a specific page and needs to login, after the user has successfully logged in, the site should forward the user to the page they wanted.
Any ideas on how this can be done in AngularJS?
OK, after some research I was able to come up with the solution below:
In app.js I added the following run method.
angular.module('MainModule', [])
...
.run(function($rootScope, $location, UserService) {
$rootScope.$on("$locationChangeStart", function(event, next, current) {
if ((!UserService.isUserLoggedIn()) && ($location.path() !== '/login')) {
$rootScope.postLoginRoute = $location.path();
$location.path('/login').replace();
}
});
});
In my loginController I was able to redirect the user to the page they desire as follows:
function loginController($scope, $location, UserService, $rootScope){
$scope.submit = function() {
if(UserService.validateCredentials($scope.username, $scope.password)){
if($rootScope.postLoginRoute){
$location.url($rootScope.postLoginRoute);
} else{
$location.path('/defaultPage');
}
$rootScope.postLoginRoute = null;
}
}
};

AngularJS ui-router redirect after log in

I have a project using AngularJS with ui-router. Everything working fine beside the redirect from login screen to preview state on the first load.
Default state is home - http://test/#/
For example, if user is not logged in - http://test/#/test/1000/details goes to login page (which it is supposed to do)
Then after user login, the system goes to default state "home - http://test/#/" but I want to go to http://test/#/requests/1000/details
How do I save the "http://test/#/requests/1000/details or stateName" to redirect after login?
I try using $stateChangeSuccess to save a log of states in the $rootscope but the first one (http://test/#/requests/1000/details) never gets saved.
Any ideas how to handle this?
Thanks.
You can add a 'previous' property to $state in your main-app's run method.
This is how I solved the problem:
// add ui-router variables to $rootScope. Comes handy in many cases, for example setting page title
angular.module('app').run(['$rootScope', '$state', '$stateParams', addUIRouterVars]);
function addUIRouterVars($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
// add previous state property
$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState) {
$state.previous = fromState;
});
}

How do I check for login or other status before launching a route in Angular with routeProvider?

Let's say I have 4 routes - 2 require the user to be logged in, 2 do not. My app init looks like:
$routeProvider.when('/open1',{templateUrl:'/open1.html',controller:'Open1'});
$routeProvider.when('/open2',{templateUrl:'/open2.html',controller:'Open2'});
$routeProvider.when('/secure1',{templateUrl:'/secure1.html',controller:'Secure1'});
$routeProvider.when('/secure2',{templateUrl:'/secure2.html',controller:'Secure2'});
Routes /open1 and /open2 are open to all, while routes /secure1 and /secure2 require the user to be logged in and, if not, take some action, e.g. redirect to login or launch a warning. I can determine the user's state by using my Auth service and calling, e.g., Auth.isLogin(). So the result would be:
going to /open1 and /open2 always go to the template and controller declared above
if Auth.isLogin() returns true, /secure1 and /secure2 go to the above-declared template and controller
if Auth.isLogin() returns false, /secure1 and /secure2 take some other action, e.g. $location.path('/login')
I could put logic in the Secure1 and Secure2 controllers that checks, but that is repetitive and mixes up responsibilities, makes them harder to test, etc.
Is there a way that I can use the $routeProvider to declare, "check this route and this route and if not, redirect"? I was thinking of using resolve somehow, but not quite sure how to work it in (docs on resolve are not very clear, and few helpful examples).
EDIT:
based on the answers below, it appears there are three philosophies for doing this:
Using resolve to check logged in and fail the promise, and then catching the $routeChangeError event to redirect http://www.sitepoint.com/implementing-authentication-angular-applications/
Using just $routeChangeStart event to check logged in and redirect http://arthur.gonigberg.com/2013/06/29/angularjs-role-based-auth/
Using just resolve to check logged in and redirect http://midgetontoes.com/blog/2014/08/31/angularjs-check-user-login
The 2nd option is what the two answerers have suggested.
As in my comments above, there are 3 different paths (plus the ability to use a directive if you want to control it from within html templates). I ended up following
https://midgetontoes.com/angularjs-check-user-login/
which essentially is as follows:
$routeProvider.when('/secure', {
templateUrl: '/secure.html',
controller: 'Secure',
resolve:{
loggedIn:onlyLoggedIn
}
});
And then onlyLoggedIn:
var onlyLoggedIn = function ($location,$q,Auth) {
var deferred = $q.defer();
if (Auth.isLogin()) {
deferred.resolve();
} else {
deferred.reject();
$location.url('/login');
}
return deferred.promise;
};
Simple, works like a charm. If I ever need a directive, I will pull this piece into a service.
This blog post deals with user authentication in AngularJS using directives.
The $route service emits $routeChangeStart before a route change.
If you don't use directives, you can catch that event by calling app.run (you can place it after the code where you define the routes [app.config]). For example:
For full disclosure I use ui.router and this is an adapted code from $stateChangeStart I use in my app
var app = angular.module('app');
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/open1',{templateUrl:'/open1.html',controller:'Open1'});
$routeProvider.when('/open2',{templateUrl:'/open2.html',controller:'Open2'});
$routeProvider.when('/secure1',{templateUrl:'/secure1.html',controller:'Secure1'});
$routeProvider.when('/secure2',{templateUrl:'/secure2.html',controller:'Secure2'});
}]);
app.run(['$rootScope', '$location', 'Auth', function($rootScope, $location, Auth) {
$rootScope.$on('$routeChangeStart', function(event, currRoute, prevRoute){
var logged = Auth.isLogin();
//check if the user is going to the login page
// i use ui.route so not exactly sure about this one but you get the picture
var appTo = currRoute.path.indexOf('/secure') !== -1;
if(appTo && !logged) {
event.preventDefault();
$location.path('/login');
}
});
}]);
I had the same problem and I did it this way:
var app = angular.module('myModule',["ui-bootstrap"]);
And then listen for a locationchange in the app (this will also trigger onEnter of a page)
app.run(function ($rootScope, $location, $cookieStore) {
$rootScope.$on("$locationChangeStart", function (event, next, current) {
//Here you can check whatever you want (servercall, cookie...)
});
}
I Hope this helps!

Resources