2014-10-03 80 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()。這迫使頁面刷新並更新導航視圖。