15

I'm a newbie to angularjs.

My problem is that I have a User Controller for handling Login and Logout. I have also another controller to load a header menu for my site.

If the user logs in to the site my isAuthenticated variable is set to true. If the variable is set to true the header should be change but, so I think the controller must be reloaded to change the header view.

Here the code of my HeaderController:

myapp.controller('HeaderController', ['$scope', '$location', '$window', 'AuthenticationService',  
    function HeaderController($scope, $location, $window, AuthenticationService) {
        $scope.isAuthenticated = AuthenticationService.isAuthenticated;

        if (AuthenticationService.isAuthenticated) {
            $scope.user.vorname = $window.sessionStorage.user.vorname;
        }
    }
]);

Here's the code of my HeaderDirective:

myapp.directive('appHeader', function() {
  return {
    restrict: 'E',
    link: function(scope, element, attrs) {
      if (attrs.isauthenticated == 'false') {
        scope.headerUrl = 'views/header/index.html';
      } else {
        scope.headerUrl = 'views/header/isAuthenticated.html';
      }
    },
    template: '<div ng-include="headerUrl"></div>'
  }
});

My index.html:

<div ng-controller="HeaderController">
  <app-header isauthenticated="{{isAuthenticated}}"></app-header>
</div>

How can I reload the controller if the user logs in to the page?

PS: Please excuse my poor pronunciation.

Don Branson
  • 13,631
  • 10
  • 59
  • 101
Rico Berger
  • 387
  • 2
  • 4
  • 15

2 Answers2

17

Add this piece of code after the user is authenticated:

// To refresh the page
$timeout(function () {
    // 0 ms delay to reload the page.
    $route.reload();
}, 0);

Don't forget to include $timeout and $route in your controller.

myapp.controller('HeaderController', ['$scope', '$location', '$window', 'AuthenticationService', '$timeout', '$route',
function HeaderController($scope, $location, $window, AuthenticationService, $timeout, $route)
falsarella
  • 12,217
  • 9
  • 69
  • 115
mpatel
  • 348
  • 2
  • 13
  • Thanks. To refresh a dynamic table, i used `$scope.$apply`. It worked well on Chrome browser on desktop. However, it did not refresh automatically on android webview. Your technique of reloading using `$route` worked on android webview 4.4.2 – nagu Oct 11 '15 at 10:14
13

There's no need to reload your controller. Angular is smart enough to change the template when the $scope.isAuthenticated state changes.

One problem I see in your code is that once the $scope.isAuthenticated is defined it does not change anymore. I suppose you are setting AuthenticationService.isAuthenticated = true when user logs in but that change aren't being propagated to the $scope.isAuthenticated property because in JavaScript scalar values are copied by value instead of by reference.

There are many approaches, such as changing the AuthenticationService.isAuthenticated property from a boolean to a function:

angular.module('auth', [])
.factory('AuthenticationService', function () {
    // private state
    var isAuthenticated = false;

    // getter and setter
    var auth = function (state) {
        if (typeof state !== 'undefined') { isAuthenticated = state; }
        return isAuthenticated;
    };

    // expose getter-setter
    return { isAuthenticated: auth };
});

Then assign that function to the $scope:

$scope.isAuthenticated = AuthenticationService.isAuthenticated;

Then use the function in your template (don't forget the parens)

<app-header isauthenticated="{{ isAuthenticated() }}"></app-header>

Edit:

While writing a plunk to show you a working example I have realized that the link function of the directive is not called more than once, so as exposed in this stackoverflow thread I just modified the directive to observe changes in the isauthenticated attribute:

angular.module('directives', [])
.directive('appHeader', function() {
  var bool = {
    'true': true,
    'false': false
  };

  return {
    restrict: 'E',
    link: function (scope, element, attrs) {
      attrs.$observe('isauthenticated', function (newValue, oldValue) {
        if (bool[newValue]) { scope.headerUrl = 'authenticated.html'; }
        else { scope.headerUrl = 'not-authenticated.html'; }
      });
    },
    template: '<div ng-include="headerUrl"></div>'
  }
});

And here is the working example

Community
  • 1
  • 1
Pau Fracés
  • 1,077
  • 10
  • 22
  • Thanks, this is what I'm searching. – Rico Berger Oct 03 '14 at 08:13
  • unfortunately, this answer kinda fails for everyone searching for how to actually reload a controller :(. Yes, its not needed in this case, but there are other use cases (such as writing infrastructure that can re-initialize bits of the ui following receipt of an event) – George Mauer Jan 25 '18 at 18:58
  • 1
    @GeorgeMauer I don't understand why a controller reolad is needed in your use case neither. Can you give more context? (maybe is better to open a new SO question linking to this one as an invalid approach for your needs) – Pau Fracés Jan 25 '18 at 19:07