Reputation: 2748
I'm trying to build a header directive that:
I'm using a custom login service that captures this information, and broadcasts the events login
and logout
. I'm successfully listening to these events in both the header's controller and directive.
How can I reload the directive on these events?
loginService.js:
angular.module("app")
.service("loginService", ["$http", "$rootScope", function ($http, $rootScope) {
var loggedIn = false,
_username = "";
this.logIn = function (username, password) {
// do some validation...
loggedIn = ...validation was successful;
_username = username;
if (loggedIn) {
$rootScope.$broadcast("login");
}
};
this.getUsername = function () {
return _username;
};
this.isLoggedIn = function () {
return loggedIn;
};
this.logOut = function () {
loggedIn = false;
$rootScope.$broadcast("logout");
};
}]);
headerController.js
angular.module("app")
.controller("headerController", ["loginService", "$rootScope", "$location", function (loginService, $rootScope, $location) {
this.isLoggedIn = loginService.isLoggedIn();
this.username = "";
$rootScope.$on("login", function (event) {
this.isLoggedIn = loginService.isLoggedIn();
this.username = loginService.getUsername();
});
this.logOut = function () {
loginService.logOut();
this.isLoggedIn = loginService.isLoggedIn();
this.username = "";
$location.path("/login"); // redirecting
};
}]);
header.html:
<header ng-controller="headerController as header">
<span ng-if="header.isLoggedIn">{{header.username}} <button ng-click="header.logOut()">Log Out</button></span>
</header>
headerDirective.js
angular.module("app")
.directive("header", function () {
return {
restrict: "A",
transclude: false,
templateUrl: "app/header/header.html",
controller: "headerController",
link: function (scope, element, attrs) {
scope.$on("login", function (event) {
// show the ng-if in header.html??
});
scope.$on("logout", function (event) {
// hide the ng-if in header.html??
});
}
};
});
I'm using this as <div header></div>
.
Upvotes: 1
Views: 7529
Reputation: 1942
Your solution is not great, usage of event broadcasting is always prone to errors and generally difficult to test and debug. What you need to do is to create a service which stores the current profile object and store a reference to it in the header directive (and other services which may use/modify the current user).
The Service
'use strict';
(function() {
function AuthService() {
var Auth = {
User: User //call some API for user authentication if using sessions
};
return Auth;
}
angular.module('app')
.factory('Auth', AuthService);
})();
Your header directive
'use strict';
//do not use "header" as the name of directive
angular.module('app')
.directive('navbar', () => ({
templateUrl: 'components/navbar.html',
restrict: 'E',
controller: function(Auth){
this.user = Auth.User;
},
controllerAs: 'navbar'
}));
Upvotes: 0
Reputation: 616
It looks like there are some fundamental issues with the directive that will not allow this to work:
1) Declared as an Attribute Directive:
You've create a header attribute directive: restrict: "A",
but you are using it as an element directive: <header ng-controller...</header>
. restrict property should be restrict: "E"
. Or you haven't used the directive as others have commented.
2) Transclude is false You have set transclude to false but you are attempting to use the directive with contents so transclude should be true.
To solve your issue I would suggest this as a solution: 1. Declare your header directive in its parent container view as just this.
<ian-header></ian-header>
ianHeader.html
<header>
<span ng-if="header.isLoggedIn">{{header.username}} <button ng-click="header.logOut()">Log Out</button></span>
</header>
ianHeader.js
angular.module("app")
.directive("ianHeader", function () {
return {
restrict: "E",
templateUrl: "app/header/ianHeader.html",
link: function (scope, element, attrs) {
scope.header = {isLoggedIn: false};
scope.$on("login", function (event) {
// show the ng-if in header.html??
scope.header.isLoggedIn = true;
});
scope.$on("logout", function (event) {
// hide the ng-if in header.html??
scope.header.isLoggedIn = false;
});
}
};
});
Upvotes: 1
Reputation: 671
If you would provide a JS snippet would be easier but anyway one approach might be:
angular.module("app")
.directive("header", function () {
return {
restrict: "A",
transclude: false,
templateUrl: "app/header/header.html",
controller: "headerController",
link: function (scope, element, attrs) {
scope.$on("login", function (event)
{
//header should be the controllerAs you declared
//If you would provide JS snippet would be easier to debbug
scope.$parent.header.isLoggedIn= true;
// show the ng-if in header.html??
});
scope.$on("logout", function (event)
{
scope.$parent.header.isLoggedIn = false;
// hide the ng-if in header.html??
});
}
};
});
Upvotes: 0