AngularJS-afficher / masquer les éléments nav si l'utilisateur est connecté
J'ai une application AngularJS d'une page, travaillant avec Express, node.JS, et MongoDB via Mongoose. Utilisation du passeport pour la gestion et l'authentification des utilisateurs.
j'aimerais que les éléments de la barre de navigation changent selon qu'un utilisateur est connecté ou non. Je vais avoir de la difficulté à trouver comment la mettre en œuvre.
je découvre si un utilisateur est connecté via un http
demande:
le serveur.js
app.get('/checklogin',function(req,res){
if (req.user)
res.send(true);
else
res.send(false);
Sur le front-end, j'ai un NavController
appel à L'aide D'Angular$http
service:
NavController.js
angular.module('NavCtrl',[]).controller('NavController',function($scope,$http) {
$scope.loggedIn = false;
$scope.isLoggedIn = function() {
$http.get('/checklogin')
.success(function(data) {
console.log(data);
if (data === true)
$scope.loggedIn = true;
else
$scope.loggedIn = false;
})
.error(function(data) {
console.log('error: ' + data);
});
};
};
Dans mon nav, je suis en utilisant ng-show
et ng-hide
pour déterminer les sélections doivent être visibles. Je suis également le déclenchement de l' isLoggedIn()
fonction lorsque l'utilisateur clique sur les éléments de nav, vérifier si l'utilisateur est connecté pendant chaque clic.
index.html
<nav class="navbar navbar-inverse" role="navigation">
<div class="navbar-header">
<a class="navbar-brand" href="/">Home</a>
</div>
<ul class="nav navbar-nav">
<li ng-hide="loggedIn" ng-click="isLoggedIn()">
<a href="/login">Login</a>
</li>
<li ng-hide="loggedIn" ng-click="isLoggedIn()">
<a href="/signup">Sign up</a>
</li>
<li ng-show="loggedIn" ng-click="logOut(); isLoggedIn()">
<a href="#">Log out</a>
</li>
</ul>
</nav>
Problème
il y a d'autres endroits dans mon application où l'utilisateur peut se connecter/Se Déconnecter, en dehors du champ D'application du NavController. Par exemple, il y a un bouton de connexion sur la page de connexion, qui correspond au LoginController. J'imagine qu'il y a une meilleure façon d'implémenter ceci dans toute mon application.
Comment puis-je surveiller si req.user
true
sur l'arrière et est-ce que mes articles nav répondent en conséquence?
4 réponses
vous pouvez utiliser $rootScope
pour partager des informations à travers l'ensemble de l'application:
.controller('NavController',function($scope,$http, $rootScope) {
$scope.isLoggedIn = function() {
$http.get('/checklogin')
.success(function(data) {
console.log(data);
$rootScope.loggedIn = data;
})
.error(function(data) {
console.log('error: ' + data);
});
};
};
maintenant vous pouvez changer la valeur de loggedIn
à partir d'autres endroits dans votre application en accédant $rootScope.loggedIn
de la même manière que dans le code ci-dessus.
cela dit, vous devez abstraire le code pertinent en un service et une directive. Cela vous permettrait d'avoir une place centrale à manipuler, connexion, déconnexion, et l'état d' $rootScope.loggedIn
. Si vous publiez le reste du code je pourrais vous aider avec plus concret en réponse
Vous pouvez diffuser cet événement lorsque l'utilisateur se connecte avec succès. Si l'utilisateur est connecté, vous pouvez garder une variable en mémoire qui indique si vous avez une session valide ou non. Vous pouvez utiliser une authentification basée sur un token qui est définie du côté du serveur:
services.factory('UserService', ['$resource',
function($resource){
// represents guest user - not logged
var user = {
firstName : 'guest',
lastName : 'user',
preferredCurrency : "USD",
shoppingCart : {
totalItems : 0,
total : 0
},
};
var resource = function() {
return $resource('/myapp/rest/user/:id',
{ id: "@id"}
)};
return {
getResource: function() {
return resource;
},
getCurrentUser: function() {
return user;
},
setCurrentUser: function(userObj) {
user = userObj;
},
loadUser: function(id) {
user = resource.get(id);
}
}
}]);
services.factory('AuthService', ['$resource', '$rootScope', '$http', '$location', 'AuthenticationService',
function ($resource, $rootScope, $http, $location, AuthenticationService) {
var authFactory = {
authData: undefined
};
authFactory.getAuthData = function () {
return this.authData;
};
authFactory.setAuthData = function (authData) {
this.authData = {
authId: authData.authId,
authToken: authData.authToken,
authPermission: authData.authPermission
};
// broadcast the event to all interested listeners
$rootScope.$broadcast('authChanged');
};
authFactory.isAuthenticated = function () {
return !angular.isUndefined(this.getAuthData());
};
authFactory.login = function (user, functionObj) {
return AuthenticationService.login(user, functionObj);
};
return authFactory;
}]);
services.factory('AuthenticationService', ['$resource',
function($resource){
return $resource('/myapp/rest/auth/',
{},
{
'login': { method: "POST" }
}
);
}]);
services.factory('authHttpRequestInterceptor', ['$injector',
function ($injector) {
var authHttpRequestInterceptor = {
request: function ($request) {
var authFactory = $injector.get('AuthService');
if (authFactory.isAuthenticated()) {
$request.headers['auth-id'] = authFactory.getAuthData().authId;
$request.headers['auth-token'] = authFactory.getAuthData().authToken;
}
return $request;
}
};
return authHttpRequestInterceptor;
}]);
contrôleur:
controllers.controller('LoginCtrl', ['$scope', '$rootScope', 'AuthService', 'UserService',
function LoginCtrl($scope, $rootScope, AuthService, UserService) {
$scope.login = function () {
AuthService.login($scope.userInfo, function (data) {
AuthService.setAuthData(data);
// set user info on user service to reflect on all UI components
UserService.setCurrentUser(data.user);
$location.path('/home/');
});
};
$scope.isLoggedIn = function () {
return AuthService.isAuthenticated();
}
$scope.user = UserService.getCurrentUser();
}])
vous pouvez ajouter les données de session de l'utilisateur dans l'index.html utilisant une bibliothèque de Templiers comme EJS.
Juste ajouter ejs middleware:
var ejs = require('ejs');
// Register ejs as .html.
app.engine('.html', ejs.__express);
et puis, en retournant l'index.html affiche les données de la session dans la réponse.
res.render( "/index.html", {
session : {
user_data : JSON.stringify(req.user)
}
});
Vous aurez maintenant accès à ces données dans l'index.html, maintenant vous devez le charger dans l'application angulaire. J'ai utilisé précontrainte-ressource exemple, mais vous pouvez utiliser votre propre chemin.
vous pouvez aussi utiliser $localStorage si vous voulez que le login persiste en dehors de la session en cours. J'ai trouvé que cette bibliothèque a été super utile pour ce genre de situations. (https://github.com/grevory/angular-local-storage)