2014-10-03 76 views
6

于是我运行到这个问题,我使用ngView那里,我有一个导航栏,在整个像这样静:

​​

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

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

我已经尝试过在我的app.config路由中创建承诺,但我不知道如何将永久返回到永久视图状态。

任何帮助表示赞赏。

编辑

这里是我播我的登录服务。该火灾随时随地用户通过身份验证/登录或他们随时注销:

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; 


}); 
+0

也许[ngCloak](https://docs.angularjs.org/api/ng/directive/ngCloak)可以帮到你。或者一个$超时也许... – denisazevedo 2014-10-03 14:11:48

+0

我试着把ng-cloak放在nav.html视图的顶部div上,但它没有解决问题。 – Himmel 2014-10-03 14:14:44

+1

你也应该尝试一个服务而不是'$ rootScope'。 – 2014-10-03 14:15:02

回答

6

带着几分$ rootScope $广播和NG-隐藏的菜单上,这可以很容易地完成。看到这个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="[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> 

的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; 
    }); 
}); 
+0

我已成功地将登录/注销事件广播到NavCtrl控制器,但是,成功用户登录后,导航栏不会更改,直到用户单击某些内容为止。 – Himmel 2014-10-03 16:51:26

+0

你的意思是“导航栏不会改变,直到用户点击某些东西”?正如我理解你的问题,你想显示或隐藏导航栏根据用户的登录状态。 – zszep 2014-10-03 16:59:46

+0

广播似乎注册,因为NavCtrl console.logs“登录”,但由于某种原因,用户登录时视图不会更新......用户必须在导航栏视图更改之前点击一些东西 – Himmel 2014-10-03 17:01:32

1

OK,如果我建议的方法是不适合你的工作,这是第二个可能的解决方案(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="[email protected]" 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; 
    } 
    } 
}) 
+0

嗯,我尝试添加isLoggedIn函数以及控制器'$ watch',但是我的Auth服务比立即将用户设置为当前用户更复杂。它必须进行身份验证,然后通过他们的Id号找到用户。我会在上面发布整个工厂。 – Himmel 2014-10-03 22:03:45

+0

好吧,我怀疑你的身份验证代码中存在一些阻止代码工作的复杂性。如果你有另一个依赖步骤(如通过id查找用户),你需要使用promise。无论如何,我很高兴你解决了你的问题。 – zszep 2014-10-04 06:05:17

+0

非常感谢您的帮助。 – Himmel 2014-10-04 17:34:07

0

@zszep $广播答案的问题解决了一个警告。有必要在NavCtrl中的每个$ scope.isHidden命令之后添加$scope.$apply()。这迫使页面刷新并更新导航视图。