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.

0

2 Answers 2

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)
Sign up to request clarification or add additional context in comments.

1 Comment

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
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

3 Comments

Thanks, this is what I'm searching.
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)
@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)

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.