I've recently added a login feature to my AngularJS app.
I have a modal login, a login service, and its associated login controller. The modal works fine and does indeed return the user/password, which I can capture in my app.js in the .then() section here - loginService.loginModal().then. So far, so good.
However, I'm trying to SUSPEND state in my app.js. Currently I'm having issues with this, as my application continues to render the main page in the background as soon as my login modal appears. This also means that I can't display the proper userId on the main page.
I've tried to use event.preventDefault();, then $state.go once the user is authenticated; however, the prevent is causing an infinite loop in Angular.
(function () {
'use strict';
angular.module('rg', [
'ui.router',
'ui.bootstrap',
'ui.dashboard',
'kendo.directives'
]).run(['$rootScope', '$state', 'userService', 'loginService', init]);
function init($rootScope, $state, userService, loginService) {
$rootScope.rageSessionVars = {};
$rootScope.$state = $state;
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
var requireLogin = toState.data.requireLogin;
if (requireLogin && typeof $rootScope.userID == "undefined") {
//event.preventDefault(); // CAUSING AN INFINITE LOOP ERR IN ANGULAR !!!
// THE APP NEEDS TO BE SUSPENDED HERE UNTIL USER IS AUTHENTICATED !!
loginService.loginModal().then(function (user) {
$rootScope.userID = user.userId;
initRz();
return $state.go(toState.name, toParams);
})
}
});
function initRz() {
userService.initRazor(razorEnvJson).then(function (data) {
var response = data.status;
if (response.match(/SUCCESS/g)) {
userService.openUserSession(razorEnvJson).then(function (data) {
var sessionID = data.data[0];
$rootScope.rageSessionVars.sessionID = sessionID;
$rootScope.rageSessionVars.userID = $rootScope.userID;
});
}
});
}
}
})();
And here is my routing config. It's note-worthy to say that I ONLY use the 'main' route, as my left nav menu contains a Kendo treeview in place of a standard routing menu:
angular
.module('rage')
.config(config);
function config($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/dashboard");
$stateProvider
.state('main', {
url: "/dashboard",
templateUrl: "app/views/dashboard.html",
controller: 'MainCtrl',
data: { pageTitle: 'RG', requireLogin: true }
})
.state('login', {
url: "/login",
templateUrl: "app/views/login-view.html",
controller: 'LoginCtrl'
}
**** UPDATED $stateChangeStart EVENT CODE ****
I get past the if (requireLogin section, but once it hits $state.go it throws an error: TypeError: Cannot read property 'requireLogin' of undefined. So, I failed to re-route to the login view.
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
var requireLogin = toState.data.requireLogin;
if (requireLogin && typeof $rootScope.userID == "undefined") {
$state.go('login'); // ERROR WHEN ATTEMPTING TO RE-ROUTE !!!
}
});
* UPDATE, SEPT 18, 2015, USING RESOLVE IN UI-ROUTER *
Using resolve: in ui-router worked out for the most part; except I'm still seeing some page-rendering in the background. I was hoping to suspend all view-rendering UNTIL my loginService was resolved.
function config($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/dashboard");
$stateProvider
.state('main', {
url: "/dashboard",
templateUrl: "app/views/dashboard.html",
controller: 'MainCtrl',
data: { pageTitle: 'RAGE', requireLogin: true },
resolve: {
authUser: ['$rootScope', 'loginService', 'userService', function ($rootScope, loginService, userService) {
return loginService.loginModal().then(function (user) {
$rootScope.userID = user.userId;
initSession(user, $rootScope, loginService, userService);
return user;
})
}]
}
})
.state('login', {
url: "/login",
templateUrl: "app/views/login-view.html",
controller: 'LoginCtrl'
})
}
function initSession(user, $rootScope, loginService, userService) {
userService.getInitParams().then(function (envJson) {
$rootScope.rageSessionVars = razorEnvJson;
userService.initRz(envJson).then(function (data) {
var response = data.status;
if (response.match(/SUCCESS/g)) {
userService.openUserSession(envJson).then(function (data) {
var sessionID = data.data[0];
$rootScope.rageSessionVars.sessionID = sessionID;
$rootScope.rageSessionVars.userID = $rootScope.userID; // *** HOW TO SUSPEND ALL CODE UNTIL userID IS ASSIGNED ??? ***
console.log("sessionID = " + sessionID);
$rootScope.rageSessionVars.currDashboardName = "Default";
});
}
});
I'd like to know if I'm missing something in my logic. Perhaps there's a Promise that I need to implement in the routing somewhere.
Your advice is appreciated.
regards,
Bob