So I'm running into this problem where I'm using ngView and I have a navigation bar that is static throughout like so:
<div ng-include="'views/nav.html'" ng-controller="NavCtrl"></div>
<div class="container-fluid" ng-view=""></div>
This nav.html, the navigation bar, displays a certain set of functions (Login, Register) if the user is logged out (using ng-show) and other menu options if the user is logged in. Because of the heavy use of current user, I've put this information in the $rootScope like this: $rootScope.currentUser
- returns user object, and $rootScope.signedIn
- return boolean.
Basically, I want to delay the navbar from loading until $rootScope.signedIn
is loaded and either true or false, and $rootScope.currentUser
is an object or undefined.
I've tried messing around with creating promises in my app.config routes, but I'm not sure how I can return a promise to the permanent view state.
Any help is appreciated.
Edit:
Here is the service in which I broadcast my login. This fires anytime a user is authenticated/logged in or anytime they logout:
var authClient = new FirebaseSimpleLogin(refDownload, function(error, user) {
if (error) {
incorrectLogin(error.code);
}
if (user) {
// user authenticated
$rootScope.$broadcast('login');
correctLogin(user.id);
} else {
// user is logged out
$rootScope.$broadcast('logout');
}
});
This service is injected into the NavCtrl controller in the following way:
$scope.isHidden = true;
$scope.$on('login', function() {
console.log('login broadcast');
$scope.isHidden = false;
});
$scope.$on('logout', function() {
console.log('broadcast logout');
$scope.isHidden = true;
});
The template for this controller is nav.html that looks like this:
<div class="col-xs-4 centered" id="nav-hover" ng-show="isHidden">
<ul class="nav navbar-nav">
<li id="nav-login"><a ng-href="#/login"><span class="glyphicon glyphicon-log-in"> Login</span></a></li>
</ul>
</div>
<div class="col-xs-4 centered" id="nav-hover" ng-show="isHidden">
<ul class="nav navbar-nav">
<li id="nav-login"><a ng-href="#/register"><span class="glyphicon glyphicon-edit"> Register</span></a></li>
</ul>
</div>
<div class="col-xs-2 centered" id="nav-hover">
<ul class="nav navbar-nav" ng-hide="isHidden">
<li ng-class="{{ chatCat.active }}"><a ng-href="{{ chatCat.url }}"><span class="{{ chatCat.icon }}"></span></a></li>
</ul>
</div>
Again, this view is bound to NavCtrl. When logging users in, I use AuthCtrl as follows:
$scope.login = function() {
if ($scope.user !== undefined) {
Auth.login($scope.user);
$location.path('/dexter');
} else {
console.log('nothing entered');
}
};
When I try to login, the nav view does not update with the new values, although the broadcast is fired from the service with 'logged in'.
Auth service:
'use strict';
app.factory('Auth',
function($rootScope, $location, $firebase, $firebaseSimpleLogin, firebaseUrl) {
var refDownload = new Firebase(firebaseUrl + 'housemates');
var sync = $firebase(refDownload);
var ref = sync.$asObject();
var authClient = new FirebaseSimpleLogin(refDownload, function(error, user) {
if (error) {
incorrectLogin(error.code);
}
if (user) {
// 1
// user authenticated
correctLogin(user.id);
} else {
// user is logged out
// $rootScope.signedIn = false;
}
});
var Auth = {
housemates: ref,
changeColor: function(color) {
var id = $rootScope.currentUser.id.toString();
refDownload.child(id).update({ color: color });
$rootScope.currentUser.color = color;
},
create: function(authUser, usr) {
refDownload.child(authUser.id).set({
initials: usr.initials,
email: authUser.email,
password: usr.password,
color: 'Blue',
id: authUser.id,
uid: authUser.uid,
rememberMe: true,
});
},
// 3
findById: function(id) {
refDownload.on('value', function(snapshot) {
var userObject = snapshot.val();
// 4 - sets currentUser
//$rootScope.currentUser = userObject[id];
var currentUser = userObject[id];
Auth.setUser(currentUser);
// $rootScope.signedIn = true;
}, function (error) {
console.log(error);
});
},
login: function(user) {
authClient.login('password', {
email: user.email,
password: user.password,
rememberMe: true
});
},
logout: function() {
delete $rootScope.currentUser;
delete $rootScope.signedIn;
delete $rootScope.error;
return authClient.logout();
},
register: function(user) {
var userSimple = user;
authClient.createUser(user.email, user.password, function(error, user) {
if(!error) {
var userComplex = user;
Auth.login(userSimple);
Auth.create(userComplex, userSimple);
return user;
} else {
console.log(error);
}
});
},
setUser: function(aUser) {
console.log('setuser ran');
$rootScope.currentUser = aUser;
console.log('setUser: ' + $rootScope.currentUser);
},
isLoggedIn: function() {
console.log($rootScope.currentUser);
return ($rootScope.currentUser) ? $rootScope.currentUser : false;
},
};
// 2
function correctLogin(id) {
Auth.findById(id);
}
function incorrectLogin(error) {
alert(error);
$rootScope.error = error;
}
return Auth;
});
The API is called “ RESOLVE ,” where all data will be loaded on the route before the route executes the page the user visits. I summarize from the Angular’s official site.
In fact, Angular has provided API to handle load initial data problem. However, beginners like me are lazy to read the entire documentation on Angular’s official website. The API is called “ RESOLVE ,” where all data will be loaded on the route before the route executes the page the user visits. I summarize from the Angular’s official site.
Since we don’t want to display a blank dynamic component while waiting for the HTTP request, we can pre-fetch the data prior to activating the route. In Angular 2, you accomplish this using the Resolve guard. This tutorial will use the Tour of Heroes project from the angular.io website as an example.
Sometimes in Angular, you gotta wait for multiple HTTP requests to complete before displaying a page. That's when you should turn to forkJoin. The forkJoin operator gives you the last emitted value from any number of Observable s. However, it only does that once they all complete.
With a bit of $rootScope.$broadcast and ng-hide on the menu, this could be easily accomplished. See this plunker
The html:
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="[email protected]" src="https://code.angularjs.org/1.2.25/angular.js" data-semver="1.2.25"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div ng-include="'nav.html'" ng-controller="NavCtrl" ng-hide="isHidden"></div>
<button class="btn" ng-click="login()">Login</button>
<button class="btn" ng-click="logout()">Logout</button>
</body>
</html>
The javascript:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $rootScope) {
$scope.login = function() {
$rootScope.$broadcast("login");
}
$scope.logout = function() {
$rootScope.$broadcast("logout");
}
});
app.controller('NavCtrl', function($scope) {
$scope.isHidden = true;
$scope.$on('login', function() {
console.log("logged in");
$scope.isHidden = false;
});
$scope.$on('logout', function() {
console.log("logged out");
$scope.isHidden = true;
});
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With