I'm a beginner when it comes to AngularJS and currently working on building a website that has a navigation bar dependent on the user's login status. My approach involves using a state model design with the Nav controller as the parent state for all pages, which is functioning well.
app.config(function ($stateProvider, $httpProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('login');
$stateProvider
.state('admin', {
templateUrl: 'partials/Nav.html',
controller: 'NavigationController'
})
.state('users', {
url:'/users',
templateUrl:'partials/Users.html',
controller: 'UserController',
parent: 'admin'
})
.state('devices', {
url:'/devices',
templateUrl:'partials/Devices.html',
controller: 'DeviceController',
parent: 'admin'
}) ...
However, I now need to keep track of the user's state and I believe using a Service for this purpose would be the best approach. Therefore, I've created a service called UserStatus
that monitors the user's state (authentication and username). This service is updated by other controllers as needed, and everything is functioning as expected.
(function(){
var app = angular.module('butler-user-status', []);
app.service( 'UserStatusService', ['$http', function($http) {
//
// As a service, the 'this' when the code is called will likely point to other things.
// To avoid this issue, I save 'this' in a local variable and then the functions can
// refer to that variable and it will always be the right one!
//
console.log('User Status: Initializing service...');
var userStatusService = this;
userStatusService.state = {currentUsername: '',
authenticated: false};
$http.get('/currentUser', {})
.success(function(data, status, headers, config){
// console.log('currentUser responded with data: '+JSON.stringify(data.username));
if (data.username != null) {
console.log('UserStat: on success name='+data.username);
console.log('UserStat: on success authenticated='+true);
};
}).error(function(){
// console.log('currentUser responded with error');
console.log('UserStat: on error');
userStatusService.state.currentUsername = '';
userStatusService.state.authenticated = false;
});
this.login = function(username) {
console.log('Login: Setting username and authenticated: username='+username);
userStatusService.state.currentUsername = username;
userStatusService.state.authenticated = true;
console.log('Login: user logged in');
};
this.logout = function() {
userStatusService.state.authenticated = false;
console.log('Login: user logged out');
};
}]);
})();
Next, I wanted the Nav controller to monitor changes in the user status, so I implemented a $scope.$watch()
on a variable in the service and updated the controller's variables when the service changed. This way, the HTML page could adjust its display based on the controller's variables.
(function() {
var app = angular.module('butler-navigation', ['butler-user-status']);
app.controller('NavigationController', ['$scope', 'UserStatusService', function($scope, UserStatusService) {
var navigationController = this;
var isAuthenticated = UserStatusService.state.authenticated;
var currentUsername = UserStatusService.state.currentUsername;
console.log('Butler-Nav: at init: username ='+UserStatusService.state.currentUsername);
console.log('Butler-Nav: at init: auth = '+ UserStatusService.state.authenticated);
$scope.$watch('UserStatusService.state', function (newValue, oldValue) {
console.log('Butler-Nav: Updating isAuthenticated to:'+newValue+' from '+oldValue);
navigationController.isAuthenticated = newValue;
});
}]);
})();
However, I'm facing an issue where the initial callback to the $watch
listener returns undefined values for both the newValue and oldValue. Even though I've set real values in the service, not nulls. What could I be doing wrong? Any assistance would be greatly appreciated from a novice like me.