0

I am doing token based authentication using MEAN stack. My application has to show Home, Signin and Signup when there is no token present i.e when a user is not logged in and Home, Me and Logout when there is a token i.e user is logged in. All my server side functionality is working fine with Signin,Signup,Logout. URL redirection in the address bar and rendering of the view is happening correctly , but the Menu items are not updating accordingly.Its getting updated only when i hit a manual refresh. Please help !

Index.html (Omitted includes):

<body ng-app="app">
    <div class="navbar navbar-inverse navbar-fixed-top" role="navigation" data-ng-controller="authCtrl">
       <!-- data-ng-controller="authCtrl" -->
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="#/">Angular Restful Auth</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a ng-href="#/">Home</a></li>
                    <li data-ng-show="token"><a ng-href="#/me">Me</a></li>
                    <li data-ng-hide="token"><a ng-href="#/login">Signin</a></li>
                    <li data-ng-hide="token"><a ng-href="#/register">Signup</a></li>
                    <li data-ng-show="token"><a ng-click="logout()">Logout</a></li>                    
                </ul>
            </div><!--/.nav-collapse -->
        </div>
    </div>
    <div class="container" ng-view="">
    </div> <!-- /container -->
    </body>

app.js:

'use strict';

var app = angular.module('app', ['ngRoute', 'authControllers', 'authServices']);
var authControllers = angular.module('authControllers', []);
var authServices = angular.module('authServices', []);

var options = {};
options.api = {};
//dev URL
options.api.base_url = "http://localhost:3000";

app.config(['$locationProvider', '$routeProvider',
function($location, $routeProvider) {
  $routeProvider.
  when('/', {
    templateUrl: 'partials/home.html',
    controller: 'authCtrl'
  }).
  when('/login', {
    templateUrl: 'partials/signin.html',
    controller: 'authCtrl'
  }).
  when('/register', {
    templateUrl: 'partials/signup.html',
    controller: 'authCtrl'
  }).
  when('/me', {
    templateUrl: 'partials/me.html',
    controller: 'authCtrl'
  }).
  otherwise({
    redirectTo: '/'
  });
}]);
app.config(['$httpProvider', function ($httpProvider) {
  $httpProvider.interceptors.push('TokenInterceptor');
}]);
app.run(function($rootScope, $location, $window, AuthenticationService) {
  $rootScope.$on("$routeChangeStart", function(event, nextRoute, currentRoute) {
    //redirect only if both isAuthenticated is false and no token is set
    if (nextRoute != null && nextRoute.access != null && nextRoute.access.requiredAuthentication
      && !AuthenticationService.isAuthenticated && !$window.sessionStorage.token) {
        $location.path("/login");
      }
    });
  });

authControllers.js:

authControllers.controller('authCtrl', ['$scope', '$location', '$window', 'UserService', 'AuthenticationService',
function authCtrl($scope, $location, $window, UserService, AuthenticationService) {
  //Admin User Controller (login, logout)
  $scope.logIn = function logIn(username, password) {
    if (username !== undefined && password !== undefined) {
      UserService.logIn(username, password).success(function(data) {
        AuthenticationService.isLogged = true;
        $window.sessionStorage.token = data.token;
        $location.path("/me");
      }).error(function(status, data) {
        console.log(status);
        console.log(data);
      });
    }
  }
  $scope.token = $window.sessionStorage.token;
  $scope.me = function() {
    UserService.me(function(res) {      
      $scope.myDetails = res;
    }, function() {
      console.log('Failed to fetch details');
      $rootScope.error = 'Failed to fetch details';
    })
  };
  $scope.logout = function logout() {
    if (AuthenticationService.isAuthenticated) {
      UserService.logOut().success(function(data) {
        AuthenticationService.isAuthenticated = false;
        delete $window.sessionStorage.token;
        $location.path("/");
      }).error(function(status, data) {
        console.log(status);
        console.log(data);
      });
    }
    else {
      $location.path("/login");
    }
  }
  $scope.register = function register(username, password, passwordConfirm) {
    if (AuthenticationService.isAuthenticated) {
      $location.path("/me");
    }
    else {
      UserService.register(username, password, passwordConfirm).success(function(data) {
        $location.path("/login");
      }).error(function(status, data) {
        console.log(status);
        console.log(data);
      });
    }
  }
}]);
1
  • $scope.token will only be evaluated once in your code. Primitives have no inheritance so if $window.sessionStorage.token changes you need to reassign value to $scope.token Commented Oct 24, 2015 at 22:37

2 Answers 2

1
$scope.token = $window.sessionStorage.token;

This string doesn't bind token to storage property. You should each time update you scope variable and if you are not in digest loop then call apply explicitly.

Sign up to request clarification or add additional context in comments.

8 Comments

no reason indicated in OP code to need to use $apply
@charlietfl It is common suggestion, the key phrase is if you are not in digest loop.
Every time when you manipulate data in the $window.sessionStorage.token do same with $scope.token.
@charlietfl, Yes, you are right, but it is not the whole application. Ones again it is common precept.
and one you have to be careful recommending because it is not a panacea for all issues. It's really only needed when scope is changed outside of angular core
|
0

Actually i tried a different approach that's even better to do it globally once. Injected $rootScope in my controller and assigned the SessionStorage token value.Now it works like a charm with simple change without updating $scope variable in multiple places.

authControllers.controller('authCtrl', ['$rootScope','$scope', '$location', '$window', 'UserService', 'AuthenticationService',
function authCtrl($rootScope,$scope, $location, $window, UserService, AuthenticationService) {
$rootScope.token = $window.sessionStorage.token;
}]);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.