首页 文章

等待$ rootScope值在页面加载之前在Angular中解析

提问于
浏览
6

所以我遇到了这个问题,我正在使用ngView,我有一个静态的导航栏,如下所示:

<div ng-include="'views/nav.html'" ng-controller="NavCtrl"></div>
<div class="container-fluid" ng-view=""></div>

如果用户已注销(使用ng-show),则此nav.html(导航栏)显示一组特定功能(登录,注册),如果用户已登录,则显示其他菜单选项 . 由于当前大量使用用户,我把这些信息放在$ rootScope中,如下所示: $rootScope.currentUser - 返回用户对象, $rootScope.signedIn - 返回布尔值 .

基本上,我想延迟加载导航栏,直到加载 $rootScope.signedIn 为真或假, $rootScope.currentUser 是一个对象或未定义 .

我已经尝试过在我的app.config路由中创建promises,但我不确定如何返回对永久视图状态的promise .

任何帮助表示赞赏 .

Edit

这是我广播登录的服务 . 只要用户通过身份验证/登录或注销时,就会触发此消息:

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

此服务以下列方式注入NavCtrl控制器:

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

该控制器的模板是nav.html,如下所示:

<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">&nbsp;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">&nbsp;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>

同样,此视图绑定到NavCtrl . 当用户登录时,我使用AuthCtrl如下:

$scope.login = function() {
        if ($scope.user !== undefined) {
            Auth.login($scope.user);
            $location.path('/dexter');
        } else {
            console.log('nothing entered');
        }               
    };

当我尝试登录时,导航视图不会使用新值更新,尽管广播是通过“登录”从服务触发的 .

认证服务:

'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;


});

3 回答

  • 0

    在菜单上有一些$ rootScope . $ broadcast和ng-hide,这很容易实现 . 看到这个plunker

    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="angular.js@1.2.x" 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>
    

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

    好的,如果我建议的方式不适合你,这是第二种可能的解决方案(plunker

    基本思想是拥有一个服务(在本例中为工厂),您可以在其中设置登录的用户名,然后在导航控制器中使用$ watch来监视服务中身份验证状态的更改 . 和代码:

    <!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="angular.js@1.2.x" src="https://code.angularjs.org/1.2.25/angular.js" data-semver="1.2.25"></script>
        <script src="app.js"></script>
        <script src="Auth.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>
    

    javascript:

    var app = angular.module('plunker', []);
    
    app.controller('MainCtrl', function($scope, $rootScope, Auth) {
      $scope.login = function() {
        var user = "iris"
        Auth.setUser(user);
      }
    
      $scope.logout = function() {
        Auth.setUser(null);
      }
    });
    
    app.controller('NavCtrl', function($scope, Auth) {
      $scope.isHidden = true;
    
      $scope.$watch(Auth.isLoggedIn, function (value, oldValue) {
    
        console.log("authentication changed");
    
        if(!value && oldValue) {
          console.log("logged out");
          $scope.isHidden = true;
        }
    
        if(value) {
          console.log("logged in");
          $scope.isHidden = false;
        }
    
      }, true);
    
    
    });
    

    和服务:

    app.factory('Auth', function() {
      var user;
    
      return {
        setUser: function(aUser) {
          user = aUser;
        },
        isLoggedIn: function() {
          console.log(user);
          return (user) ? user : false;
        }
      }
    })
    
  • 1

    @zszep $广播的答案解决了这个问题,但有一点需要注意 . 必须在NavCtrl中的每个$ scope.isHidden命令之后添加 $scope.$apply() . 这会强制页面刷新排序并更新导航视图 .

相关问题