Views not refreshing after user login

I have created a ionic sidebar app, that requires a user to login in order to view pages.

A Web API 2 project returns a a token which is stored in $window.localStorage.

On my view, I call isAuthenticated() in order to check if the user is logged on, and in the console it returns “true” which shows it is stored and the user is logged on.

However, it feels as if the main.html page is never “refreshed” if I can call it that, and thus the isAuthenticated() function is not performed, thus the information on the page keeps staying hidden.

I am really new to Javascript and Angularjs, but I just can’t figure out how to get this working?

Login.js

‘use strict’;

angular.module(‘ExcaliburMobile’).controller(‘LoginCtrl’, function($scope, $http, $timeout, $location, authToken, $state) {
$scope.login = function() {

  var url = 'http://localhost:60151/token';
  var user = {
    username: $scope.user.username,
    password: $scope.user.password
  };
  /*This has to be sent along with the request to Web API 2*/
  var data = 'grant_type=password&username=' + user.username + '&password=' + user.password;
  $http.post(url, data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
    .success(function(res) {
      authToken.setToken(res.access_token);
      $scope.message = 'User has been logged in successfully, you will be redicted to login page in 2 seconds.';
      $scope.closeLogin();
      startTimer();
    })
    .error(function(err) {
      //alert('failure!!');
    });
  var startTimer = function() {
    var timer = $timeout(function() {
      $timeout.cancel(timer);
      //$location.path('/app/main');
      $state.go('app.main');
      var nametynaa = authToken.isAuthenticated();
      console.log(nametynaa);
      console.log('Groot!!');
    }, 1000);
  };
};

});

authToken.js

'use strict';

/*Check if user is authenticated*/

angular.module('ExcaliburMobile').factory('authToken', function($window) {
  var storage = $window.localStorage;
  var cachedToken;
  var userToken = 'userToken';
  var authToken = {
    setToken: function(token) {
      cachedToken = token;
      storage.setItem(userToken, token);
        
      /*Only for Testing*/
      var testStorage = window.localStorage['userToken'];
      console.log(testStorage);
      /*Only for Testing*/
    },
    getToken: function() {
      if (!cachedToken)
        cachedToken = storage.getItem(userToken);

      return cachedToken;
    },
    isAuthenticated: function() {
      return !!authToken.getToken();
    },
    removeToken: function() {
     cachedToken = null;
        storage.removeItem(userToken);
    }
  };
  return authToken;
});

main.html

<ion-view view-title="Excalibur Mobile" >
  <ion-content>
    <ion-list>
      <ion-item ng-show="isAuthenticated()" ng-repeat="playlist in playlists" href="#/app/main/{{playlist.id}}">
        {{playlist.title}}
      </ion-item>
    </ion-list>
  </ion-content>
</ion-view>

app.js

// Ionic Starter App

// angular.module is a global place for creating, registering and retrieving Angular modules
// 'ExcaliburMobile' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
// 'ExcaliburMobile.controllers' is found in controllers.js
'use strict';
angular.module('ExcaliburMobile', ['ionic', 'ExcaliburMobile.controllers'])

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if (window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if (window.StatusBar) {
      // org.apache.cordova.statusbar required
      StatusBar.styleDefault();
    }
  });
})

.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider

  .state('app', {
    url: '/app',
    abstract: true,
    templateUrl: 'views/menu.html',
    controller: 'AppCtrl'
  })

  .state('app.search', {
    url: '/search',
    views: {
      'menuContent': {
        templateUrl: 'views/search.html'
      }
    }
  })

  .state('app.browse', {
    url: '/browse',
    views: {
      'menuContent': {
        templateUrl: 'views/browse.html'
      }
    }
  })

  .state('app.main', {
    url: '/main',
    views: {
      'menuContent': {
        templateUrl: 'views/main.html',
        controller: 'MainCtrl'
      },
      data: {
        requiresLogin: true
      }
    }
  })

  .state('app.single', {
    url: '/playlists/:playlistId',
    views: {
      'menuContent': {
        templateUrl: 'views/playlist.html',
        controller: 'PlaylistCtrl'
      }
    }
  })

  .state('app.register', {
    url: '/register',
    views: {
      'menuContent': {
        templateUrl: 'views/register.html',
        controller: 'RegisterCtrl'
      }
    }
  })
    .state('app.login', {
      url: '/login',
      views: {
        'menuContent': {
          templateUrl: 'views/login.html',
          controller: 'LoginCtrl'
        }
      }
    })
    .state('app.logout', {
      url: '/logout',
      views: {
        'menuContent': {
          controller: 'LogoutCtrl'
        }
      }
    });

  // if none of the above states are matched, use this as the fallback
  $urlRouterProvider.otherwise('/app/main');
});

controllers.js

'use strict';
angular.module('ExcaliburMobile.controllers', [])

.controller('AppCtrl', function($scope, $ionicModal, authToken) {
  // Form data for the login modal
  $scope.loginData = {};

  // Create the login modal that we will use later
  $ionicModal.fromTemplateUrl('views/login.html', {
    scope: $scope
  }).then(function(modal) {
    $scope.modal = modal;
  });

  // Triggered in the login modal to close it
  $scope.closeLogin = function() {
    $scope.modal.hide();
  };

  // Open the login modal
  $scope.login = function() {
    $scope.modal.show();
  };
    
  $scope.logout = function() {
    /*Only for Testing*/
    var testStorage = window.localStorage['userToken'];
    console.log(testStorage);
    /*Only for Testing*/  
    
    /*Reference authToken's removeToken function*/
    authToken.removeToken();
    
    /*Only for Testing*/
    var testStorageAfter = window.localStorage['userToken'];
    console.log(testStorageAfter);
    /*Only for Testing*/
  };
    
//   $scope.isAuthenticated = function() {
//    authToken.isAuthenticated();
//    console.log(authToken);
//  };   
})

.controller('MainCtrl', function($scope, authToken) {
  $scope.playlists = [
    { title: 'Main page', id: 1 }
  ];
  var blah = authToken.isAuthenticated();
    console.log(blah);
    console.log('blaaaaaahhhhhh');
})

//.controller('PlaylistCtrl', function($scope, $stateParams) {
//})
;

It feels as if, on app start the main page is checked and isAuthorized is fired, then login occurs, and redirected to main with $state.go(app/main), but main never fires isAuthorized again to now check that the state is updated to logged on.

If someone can please help?

Views are cached by default in newer versions of Ionic, meaning that views and their controllers are only created once, and then hidden when navigating away and shown when navigated to. It sounds like this is what’s happening - your controller is not running the code a second time because it’s not being created when you navigate to it again.

Take a look at the caching details in the docs, it should give you the info you need. It’s currently spread over a couple pages, take a look at http://ionicframework.com/docs/api/directive/ionNavView/ and http://ionicframework.com/docs/api/directive/ionView/. Post back if it doesn’t work or if you have further issues :smiley: