簡體   English   中英

AngularJS - 如果用戶已登錄,則顯示/隱藏導航項

[英]AngularJS - show/hide nav items if user is logged in

我有一個單頁的AngularJS應用程序,通過Mongoose使用Express,node.js和MongoDB。 使用Passport進行用戶管理/身份驗證。

我希望根據用戶是否登錄來更改導航欄項。 我無法弄清楚如何實現它。

我發現用戶是否通過http請求登錄:

server.js

app.get('/checklogin',function(req,res){
  if (req.user)
    res.send(true);
  else
    res.send(false);

在前端,我有一個NavController使用Angular的$http服務調用它:

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);
        });
    };
};

在我的導航中,我使用ng-showng-hide來確定哪些選項應該可見。 當用戶單擊導航項時,我還會觸發isLoggedIn()函數,檢查用戶是否在每次單擊期間登錄。

的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>

問題

我的應用程序中還有其他位置,用戶可以在NavController范圍之外登錄/注銷。 例如,登錄頁面上有一個登錄按鈕,對應於LoginController。 我想在我的整個應用程序中實現這一點有更好的方法。

我如何“觀察” req.user是否為true ,並且我的導航項是否相應地響應?

您可以使用$rootScope在整個應用程序中共享信息:

.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);
        });
    };
};

現在,您可以通過訪問$rootScope.loggedIn來改變應用程序中其他位置的loggedIn值,就像在上面的代碼中一樣。

話雖如此,您應該將相關代碼抽象為服務和指令。 這將允許您有一個中心位置來處理,登錄,注銷和$rootScope.loggedIn的狀態。 如果您發布其余的相關代碼,我可以幫助您找到更具體的答案

您可以在用戶成功登錄時廣播該事件。 如果用戶登錄,則無需繼續輪詢您的服務器,您可以在內存中保留一個變量,告知您是否有有效的會話。 您可以使用在服務器端設置的基於令牌的身份驗證:

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;
}]);

控制器:

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();         
}])

您可以使用一些模板庫(如EJS)在index.html中添加用戶的會話數據。

只需添加ejs中間件:

 var ejs = require('ejs'); // Register ejs as .html. app.engine('.html', ejs.__express); 

然后,在返回index.html時將會話數據呈現到響應中。

  res.render( "/index.html", { session : { user_data : JSON.stringify(req.user) } }); 

您現在可以在index.html中訪問此數據,現在需要將其加載到Angular應用程序中。 我使用了preload-resource示例,但您可以使用自己的方式。

如果您希望登錄在當前會話之外保持不變,也可以使用$ localStorage。 我發現這個庫對這些類型的情況非常有幫助。 https://github.com/grevory/angular-local-storage

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM