cannot forward to another page in change route event ui router - angularjs

In my application I am trying to redirect the user to get redirected to login if he is not logged in and if he is than restrict him from visiting login page And I implemented the same like this before as well but now its not working I would like to know what I am doing wrong
app.run(function ($rootScope, $state, authService) {
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
if (toState === 'home' && authService.isAuthenticated()) {
event.preventDefault();
$state.go(fromState);
}
if (toState !== 'home' && !authService.isAuthenticated()) {
event.preventDefault();
$state.go('home');
}
});
});
I have done same here as well but it was working I don't know why that was working and this is not working.
The link for the code that was working

Related

How to handle stateChangeStart event at controller level in angularjs?

I am trying to redirect to home page when specific views are refreshed in browser. If I handle stateChangeStart event on rootScope level, it all works fine and navigates to home page.
var payApp = angular.module('pay', ['ui.router', 'pay.controllers', 'pay.services', 'exceptionOverride']);
payApp.run(['$templateCache', '$rootScope', '$state', '$stateParams', '$window', '$location', function ($templateCache, $rootScope, $state, $stateParams, $window, $location) {
$templateCache.put(baseUrl, angular.element('#ui-view').html());
// Allows to retrieve UI Router state information from inside templates
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$rootScope.$on('$stateChangeSuccess', function (event, toState) {
// Sets the layout name, which can be used to display different layouts (header, footer etc.)
// based on which page the user is located
$rootScope.layout = toState.layout;
});
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams, options) {
//When payment or order page is refreshed, navigate to home
if (fromState.name == '' && (toState.name == 'payment' || toState.name == 'order')) {
$location.url('/');
}
});
var windowElement = angular.element($window);
windowElement.on('beforeunload', function (event) {
var path = $location.path();
if (path == '/payment' || path == '/order') {
event.preventDefault();
}
});
}]);
But I am trying to move this logic to a specific controller level so the stateChangeStart event will be fired only for specific views which are using this controller.
var payControllers = angular.module('pay.controllers', ['ui.bootstrap', 'ngIdle']);
payControllers.controller('payPaymentCtrl', ['$scope', '$state', '$window', '$location', 'payDataService', 'Idle', 'Keepalive', '$uibModal',
function ($scope, $state, $window, $location, service, Idle, Keepalive, $uibModal) {
var windowElement = angular.element($window);
windowElement.on('beforeunload', function (event) {
var path = $location.path();
if (path == '/payment' || path == '/paymentcreated') {
event.preventDefault();
}
});
$scope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams, options) {
//When payment or order page is refreshed, navigate to home
//Both payment and order share the same controller.
if (fromState.name == '' && (toState.name == 'payment' || toState.name == 'order')) {
$location.url('/');
}
});
$scope.paymentOption = service.GetpaymentOption();
if ($scope.paymentOption == null) {
//$state.go('home', {}, { reload: true });
//$location.path('/').replace();
$location.url('/');
}
}]);
The beforeunload event fires in the controller when a view is refreshed in browser but stateChangeStart does not fire.
Also, I tried to get rid of the stateChangeStart event from the controller level and handle to go to home page when some crucial data is missing. It gives me an error saying "Unable to load property of undefined". It appears to be trying to load some data that is bound to angular scope elements which usually appears upon some operation on home page. I need it to look like just the way when I open the home page for the first time when the application is run.
Thanks for any suggestions.

Change query param in url using UI-router

Using ui-router how can I accomplish the following URL change? For example, when a user goes to "/page?hello=True" I want the url to change to "/page?status=hello".
$stateProvider.state('page', {
url: '/page/:id?status',
controller: 'MyCtrl as myCtrl',
templateProvider: function($templateCache) {
return $templateCache.get('templates/route.html');
}
});
You can use the stateChangeStart event in the app.run method to listen for state changes into that route, and change anything you want on the params. Something like this, might need to play with toState and toParams to get it right for you...
.run(['$state', '$rootScope', function($state, $rootScope) {
$rootScope.$on('$stateChangeStart', function(e, toState, toParams, fromState, fromParams) {
if (toState.name === 'invitation') {
//change toParams to whatever you want
}
});
});

Angular UI Router dynamic states on refresh goes to 404

I'm loading states dynamically based on the current user role. But when the page is refreshed it takes to the 404 page. Also in $stateChangeStart event fromState.name is blank.
Is there a way to go to the state before refresh button was clicked? Should I store the state before refresh is pressed and then use it?
.state('404', {
url: '/404',
templateUrl: '404.tmpl.html',
controller: function ($scope, $state, APP) {
$scope.app = APP;
$scope.goHome = function () {
$state.go('default.page');
};
}
})
$urlRouterProvider.otherwise('/404');
....
$rootScope.$on('$stateChangeStart', function (e, toState, toParams, fromState, fromParams) {
//fromState.name = '' on refresh
});
Thanks in advance!
The below seems to work, not sure if this is the best approach. On before unload event save the state, then use it in $stateChangeStart.
.run(function ($rootScope, $window, $state, authService, $http, $timeout, localStorageService) {
$rootScope.$on('$stateChangeStart', function (e, toState, toParams, fromState, fromParams) {
if (authService.isLoggedIn()) {
if (toState.name === "404" && fromState.name === '' && localStorageService.get("LAST_STATE") !== "404") {
authService.loadStates($stateProviderRef).then(function () {
$state.go(localStorageService.get("LAST_STATE"), localStorageService.get("LAST_STATE_PARAMS"));
});
}
}
});
window.onbeforeunload = function () {
localStorageService.set("LAST_STATE", $state.current.name);
localStorageService.set("LAST_STATE_PARAMS", $state.params);
return null;
}
})

How to pass url to $stateChangeStart of ui-router

I use the following to redirect routes to login if a user is not logged in:
angular.module('app').run(['$rootScope', '$location', '$state', 'AuthService',
function($rootScope, $location, $state, AuthService) {
/* redirect to login if not logged in */
$rootScope.$on( '$stateChangeStart',
function(e, toState, toParams, fromState, fromParams) {
if(toState.name === "login"){
return; // already going to login
}
if(!AuthService.user) {
e.preventDefault();
$state.go('login');
}
});
}]);
How can I pass the url from the "prevented" state to the login state so that I can continue navigating to that state once logged in?
Example: User clicks link for myapp.com/#/path/to/data --> redirects to myapp.com/#/login --> user logs in --> user routed to myapp.com/#/path/to/data
I basically need /path/to/data to be sent to my login controller so that I can handle that. I cannot seem to find '/path/to/data' in any of the state or param variables in the $stateChangeStart listener.
The $state service has an href method which can create a URL given the state and its parameters. Since those are provided to the state change listener, you can create a URL and then pass it as a param to the login state.
$rootScope.$on('$stateChangeStart',
function(e, toState, toParams, fromState, fromParams) {
if (toState.name === "login") {
return; // already going to login
}
if (!AuthService.user) {
e.preventDefault();
var redirectUrl = $state.href(toState.name, toParams);
$state.go('login', {
redirect: redirectUrl
});
}
});
You'll need to add a redirect parameter to your login state so you can use that.
You can store the pre-login location in $rootScope, and then fetch it from there once login is successful
if(!AuthService.user) {
e.preventDefault();
$rootScope.pre_login_path = $location.path();
$state.go('login');
}
And then after login, you can set the login path similarly in your login controller/service (have that include dependency injection of $rootScope and $location)
$location.path($rootScope.pre_login_path);

Conditional Page Display when application opens for the first time

Hi I am just starting to learn angular && angular-ui-router and am trying to figure out how to determine when the app is opened for the first time to send the user to the login page or home page.
This is what i have so far:
codeArtApp.config(function($stateProvider, $urlRouterProvider){
$stateProvider
.state('login',{
url : '/login',
templateUrl:'App/scripts/login/loginView.html',
controller: 'loginCtrl'
})
.state('profile', {
url : '/profile',
templateUrl:'App/scripts/login/loginView.html',
controller: 'profileCtrl'
})
.state('404', {
url: '/404',
templateUrl:'App/scripts/views/404.html'
});
$urlRouterProvider.otherwise("404");
});
codeArtApp.run(['$state', '$rootScope', function($state, $rootScope, $log){
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState){
if(fromState.url === '^' && toState.url !== 'login'){
$state.go('login');
}
});
}]);
What I assumed here is that if fromState.url is set to ^ then the application is starting for the first time.
For some reason this code enters an infinite loop and I gt this stacktrace:
Now from what I can tell this happened because event if $state.go('login') gets execute toState.url is always 404.
I had hoped if $state.go('login') gets executed toState.url would have been set to login and that call would not be executed anymore.
I may not be setting this logic in the right place...
Can anyone tell me how conditionaly page displayed is achieved in Angular?
In your $urlRouterProvider.otherwise call you can pass a function instead of a string. Something like this:
$urlRouterProvider.otherwise(function($injector){
var $state = $injector.get('$state');
var Storage = $injector.get('Storage');
if (Storage.has('authToken')) {
$state.go('home');
}
else {
$state.go('login');
}
});
Hope this helps!
There is a link to working plunker, the main changes are shown in the code:
codeArtApp.run(['$state', '$rootScope',
function($state, $rootScope, $log) {
$rootScope.$on('$stateChangeStart',
function(event, toState, toParams, fromState) {
// instead of
// toState.url !== 'login'
// we compare
// toState.name !== 'login'
var shouldLogin = fromState.url === '^'
&& toState.name !== 'login';
if(shouldLogin)
{
// this way we stop current execution
event.preventDefault();
// and navigate to login
$state.go('login');
}
});
}
]);
The toState.url would contain the url, i.e. '/login' instead of 'login'. Also check the : State Change Events to see more about the event.preventDefault(); . The plunker showing the above...

Resources