Reputation: 187
I have an Angular 1.5.x application that uses Angular UI Router's $stateChangeSuccess
event to register a listener that verifies if a user is logged in on each state change to protect certain views of the application. After porting the application into a CommonJS environment via Browserify, the registered event handlers do not execute any more, but UI Router keeps changing states as previously. I need help figuring out if and why UI Router is not emitting the event or if the problem is being caused by Angular scopes behaving differently when working in a CommonJS environment. Any help is greatly appreciated, thanks!
I had angular-ui-router 1.0.0-alpha.1 installed via npm. I checked out the angular ui router github releases docs based on Chris's comment and decided to see if it worked by reverting to 0.2.18, it didn't.
The only require statements of relevance are the routes, core, and services modules.
'use strict';
var angular = require('angular');
var routes = require('./app.routes.js');
// Sub-module Dependencies
var core = require('./app.core.js');
var services = require('./services');
var layout = require('./layout');
var auth = require('./authentication');
var landing = require('./landing');
var dashboard = require('./dashboard');
var userManual = require('./user-manual');
// Define Angular Module
var app = angular.module('app', [
core,
services,
layout,
auth,
landing,
dashboard,
userManual
])
.config(html5ModeTrue)
.config(routes)
.run(runBlock);
////////////////
html5ModeTrue.$inject = ['$locationProvider'];
runBlock.$inject = ['authService'];
////////////////
function html5ModeTrue ($locationProvider) {
$locationProvider.html5Mode(true);
}
function runBlock(authService) {
authService.initialize();
}
'use strict';
routes.$inject = ['$stateProvider', '$urlRouterProvider'];
function routes($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/");
$urlRouterProvider.when('/dashboard', '/dashboard/analysis');
$stateProvider
.state('home', {
url: "/",
templateUrl: "app/landing/home.html"
})
.state('about', {
url: "/about",
templateUrl: "app/landing/about.html"
})
.state('atlas', {
url: "/atlas",
templateUrl: "app/landing/atlas.html"
})
.state('login', {
url: "/login",
templateUrl: "app/authentication/login.html",
controller: "LoginController",
controllerAs: "login"
})
.state('dashboard', {
abstract: true,
// url: "/dashboard",
templateUrl: "app/dashboard/dashboard.html",
controller: "DashboardController",
controllerAs: "dash",
restricted: true,
})
.state('dashboard.analysis', {
url: "/dashboard/analysis",
templateUrl: "app/dashboard/dashboard.analysis.html"
})
.state('dashboard.vmod', {
url: "/dashboard/vmod",
templateUrl: "app/dashboard/dashboard.vmod.html"
})
.state('dashboard.datasets', {
url: "/dashboard/datasets",
templateUrl: "app/dashboard/dashboard.datasets.html"
})
.state('dashboard.defaults', {
url: "/dashboard/defaults",
templateUrl: "app/dashboard/dashboard.defaults.html"
})
.state('dashboard.user-management', {
url: "/dashboard/user-management",
templateUrl: "app/dashboard/dashboard.user-management.html"
})
.state('user-manual', {
url: "/user-manual",
templateUrl: "app/user-manual/user-manual.html",
restricted: true
})
.state('user-manual.analysis', {})
.state('user-manual.vmod', {})
.state('user-manual.datasets', {});
}
module.exports = routes;
As shown below, angular-ui-router, which was installed via npm, is being required into the core dependencies submodule of the application
'use strict';
// Module Dependencies
require('angular-animate'); // ngAnimate
require('angular-ui-bootstrap'); // ui.bootstrap
require('angular-ui-router'); // ui.router
require('ui-leaflet'); // ui-leaflet
require('leaflet'); // Dependency for ui-leaflet
require('angular-simple-logger'); // Dependency for ui-leaflet
// Define Angular Module
var name = 'app.core';
require('angular').module(name, [
'ui.bootstrap',
'ui.router',
'ngAnimate',
'ui-leaflet',
]);
// Expose Angular Module Name For Easy Injection
module.exports = name;
This file simply serves as the entry point for the requiring the application's Angular services.
'use strict';
// Module Dependencies
var authService = require('./auth.service.js');
var userManagementService = require('./user-management.service.js');
// Define Angular Module
var name = 'app.services';
require('angular')
.module(name, [])
.factory('authService', authService)
.factory('userManagementService', userManagementService);
module.exports = name;
The initialize function in this service registers a listener to the $stateChangeSuccess
event, which never gets called.
'use strict';
authService.$inject = ['$q', '$window', '$http', '$rootScope', '$location'];
function authService ($q, $window, $http, $rootScope, $location) {
var userSession = null;
var service = {
initialize: initialize,
isLoggedIn: isLoggedIn,
getUserSession: getUserSession,
login: login,
logout: logout
};
return service;
////////////////
function initialize() {
var accessToken = $window.sessionStorage["fa-session"];
userSession = accessToken ? JSON.parse(accessToken) : null;
$rootScope.$on('$stateChangeSuccess', onStateChangeSuccess);
function onStateChangeSuccess(event, toState, fromState, fromParams) {
if (toState.restricted && isLoggedIn() === false) {
$location.path('/login');
}
}
}
function isLoggedIn() {
return userSession || false;
}
function getUserSession() {
return userSession;
}
function login(username, password) {
var deferred = $q.defer();
$http.post('/api/login', {username: username, password: password})
.then(loginComplete)
.catch(loginFailed);
return deferred.promise;
function loginComplete(response) {
userSession = {
accessToken: response.data.access_token,
username: response.data.username
};
$window.sessionStorage["fa-session"] = JSON.stringify(userSession);
deferred.resolve(userSession);
}
function loginFailed(error) {
deferred.reject(error);
}
}
function logout() {
var deferred = $q.defer();
$http.post('/api/logout', {headers: {access_token: userSession.accessToken}})
.then(logoutCompleted)
.catch(logoutFailed);
return deferred.promise;
function logoutCompleted(response) {
userSession = null;
$window.sessionStorage["fa-session"] = null;
deferred.resolve(response);
}
function logoutFailed(error) {
deferred.reject(error);
}
}
}
module.exports = authService;
Upvotes: 3
Views: 1065
Reputation: 187
So I managed to get it working by using the $transition.on* hooks Chris T mentioned in his comment. I also investigated if this $rootScope problem was occurring outside of the state change events. From what I was able to verify, $scope and $rootScope event emitters and handlers worked perfectly fine with my controllers.
.state('user-manual', {
url: "/user-manual",
templateUrl: "app/user-manual/user-manual.html",
restricted: true
})
.state('user-manual', {
url: "/user-manual",
templateUrl: "app/user-manual/user-manual.html",
// restricted: true
onEnter: function (authService, $location) {
if (!authService.isLoggedIn()) {
$location.path('/login');
}
}
})
Upvotes: 2