Handling header and footer in AngularJS

Problem

I have been trying to implement the header / footer in an Angular JS App. I was thinking of adding these as ng-include in the main index.html. However this would have worked if the header and footer are static pages. My case is slightly different... In Login page no header / footer is shown. Other pages depending on whether you are logged in or not, you have to show "Welcome user [ logout] " or "Welcome guest [ login ]".

I save the login information and isLoggedIn in a service - then use HeaderCtrl controller to copy that to $scope. The biggest problem seems to be that the whole ng-include is not refreshed on a logoff. Hence divs with ng-show hide directives will not hide/show on change. Somebody suggested using ng-switch - it also behaves the same way.

If I move the header code inside individual views then everything is fine.

A similar question is here: Refresh header page in angularjs AngularJS - Handle repeated fragments like Header and Footer

I have asked this question earlier but the answers did not help me when I moved the logged variable from the rootScope. The problem is my HeaderCtrl is only executing on a full page refresh. Not executing on Angular page navigation etc.

Here is the code: index.html:

<body ng-app="greenhornApp">
    <div id="navbar" ng-controller="HeaderCtrl"><div ng-include src="'views/partials/header.html'"></div>
    </div>
    <div class="title-spacer visible-desktop"></div>
    <!-- Add your site or application content here -->
    <div class="wrapper" ng-view></div>
</body>

header.js:

angular.module('greenhornApp')
  .controller('HeaderCtrl', ['$scope', 'LoginService', function ($scope, loginService) {
    $scope.isLoggedIn = loginService.isLoggedIn();
    $scope.session = loginService.getSession();
  }]);

header.html

<div>
  <div ng-show="isLoggedIn">
    <div class="navbar navbar-inverse navbar-fixed-top">
More stuff here....
    </div>
  </div>
</div>

I am using ng-route and angular 1.2.0-rc3. I put a breakpoint in HeaderCtrl... it gets executed only when I do a full page refresh. What am I doing wrong here?

Problem courtesy of: Hari Gangadharan

Solution

If your loginService.isLoggedIn() is bound to a primitive value instead of an object, your HeaderCtrl needs to use $watch to monitor the variable and get the new value as it changes.

For it to work without a $watch you need to make sure an object reference is passed from your loginService to your HeaderCtrl.

I made two quick Plunkers that hopefully replicates your situation well enough to give some guidance:

With primitive and $watch: http://plnkr.co/edit/LvtVEE?p=preview

With object reference and no $watch: http://plnkr.co/edit/2u2ZDE?p=preview

Solution courtesy of: tasseKATT

Discussion

EDIT: My original reasoning was wrong. Check tasseKATT's answer for that.

Here's is another way of communicating between controllers using angularJS broacasting mechanism

Here's a jsfiddle just to show the basic idea.

var module = angular.module("demo", []);

function Header ($scope){

   $scope.userIsLoggedIn = true

   $scope.$on('DO_LOGOUT',function(event){
    alert('Header is updating log-status')
    $scope.userIsLoggedIn=false
   })
}
function Dynamic($scope){

 $scope.logout =function(){
    $scope.$emit('LOGOUT_REQUESTED')
  }
}

function Root($scope) {

$scope.$on('LOGOUT_REQUESTED',function(event){
    alert('Rootscope got logout event')
    $scope.$broadcast('DO_LOGOUT')
})   
}
Discussion courtesy of: Mikael P

This recipe can be found in it's original form on Stack Over Flow.