Angular novice here. I'm trying to wrap my head around the right way to accomplish a basic template issue.
I have a header, which should read “click here to log in” when the user is not logged in, and “Welcome, Dudefellah” (and associated Settings links and whatnot) when a user is logged in.
I've written a Service that is able to return a JSON bundle including a login state and username, but I don't know what “The Angular Way” to express: “if(auth.loggedin), output partials/header.html; else output partials/header_login.html”.
I’m unclear as to whether this logic would belong in the controller, or some kind of “auth” model, or even in the view (that can't be right, right?). Any assistance would be greatly appreciated.
Within the controller once the login state is fetched create a scope variable headerTemplate and assign the name of the template depending on the login state
function MyCtrl($scope, loginService) {
$scope.auth = loginService.getLoginState();
$scope.headerTemplate = $scope.auth ? 'partials/header.html' : 'partials/header_login.html';
}
In in your markup
<div ng-include src="headerTemplate"></div>
There's a sample angular application called angular-app that does this really well. They have a security service, then a toolbar partial and directive that shows things depending on the state.
https://github.com/angular-app/angular-app/tree/master/client/src/common/security
from angular-app:
src/common/security/login/toolbar.tpl.html:
<ul class="nav pull-right">
<li class="divider-vertical"></li>
<li ng-show="isAuthenticated()">
<a href="#">{{currentUser.firstName}} {{currentUser.lastName}}</a>
</li>
<li ng-show="isAuthenticated()" class="logout">
<form class="navbar-form">
<button class="btn logout" ng-click="logout()">Log out</button>
</form>
</li>
<li ng-hide="isAuthenticated()" class="login">
<form class="navbar-form">
<button class="btn login" ng-click="login()">Log in</button>
</form>
</li>
</ul>
src/common/security/login/toolbar.js:
angular.module('security.login.toolbar', [])
// The loginToolbar directive is a reusable widget that can show login or logout buttons
// and information the current authenticated user
.directive('loginToolbar', ['security', function(security) {
var directive = {
templateUrl: 'security/login/toolbar.tpl.html',
restrict: 'E',
replace: true,
scope: true,
link: function($scope, $element, $attrs, $controller) {
$scope.isAuthenticated = security.isAuthenticated;
$scope.login = security.showLogin;
$scope.logout = security.logout;
$scope.$watch(function() {
return security.currentUser;
}, function(currentUser) {
$scope.currentUser = currentUser;
});
}
};
return directive;
}]);
You could also use ui-router which does wonders for conditional routing and for good infrastructure in general. You'll need to define two states:
myapp.config(function($stateProvider, $urlRouterProvider){
...
// Now set up the states
$stateProvider
.state('login', {
parent: account,
url: "/login",
templateUrl: "partials/header_login.html"
})
.state('auth', {
parent: account,
url: "/authorized",
templateUrl: "partials/header.html"
})
})
when you are back from your query, change state by $state.transitionTo('login') or ('auth') and the router will load the right template for you (and also the URL). in general its much better to use a good router as the basis of your app and not give ad-hoc solutions per each case. you could also read a page (I wrote) about it here