【问题标题】:Can't access authData bound to $rootScope from one of the controllers无法从其中一个控制器访问绑定到 $rootScope 的 authData
【发布时间】:2015-02-07 04:51:33
【问题描述】:

我有一个让我发疯的错误,基本上我要做的就是设置一个$rootScope.authData 属性,该属性包含用户的身份验证信息,以便我可以在不同的控制器中使用它。

但是,当我尝试这个时,它只是给我一个错误,说 $rootScope.authData 没有定义。我已经检查过,它确实是从mainCtrl 将其记录到控制台时定义的,但从tagsCtrl 将其记录到控制台时它是undefined

考虑到我可以在我的其他控制器之一中使用$rootScope.authData,这很奇怪。如果我在mainCtrl 中添加$rootScope.test = 'testing' 并在tagsCtrl 中添加控制台日志,它可以工作.

我看不出我在这里做错了什么,我已经走到了死胡同。有什么想法吗?

设置$rootScope.authData的主控制器:

flickrApp.controller('mainCtrl', ['$scope', '$rootScope', '$firebase', 'Auth', function($scope, $rootScope, $firebase, Auth) {

    Auth.$onAuth(function(authData) {
        $rootScope.authData = authData;
        console.log($rootScope.authData); //Is defined here
    });
}]);

无法访问$rootScope.authData的控制器:

flickrApp.controller('tagsCtrl', ['$scope', '$rootScope', '$firebase', function($scope, $rootScope, $firebase) {

console.log($rootScope.authData); //Is not defined here

}]);

编辑:在收到 Bricktop 的一些反馈后,我尝试为此创建一个服务,结果如下:

flickrApp.service('shared', ['$scope', 'Auth', function($scope, Auth) {

    //Auth is a wrapper that points to my firebase reference

    Auth.$onAuth(function(authData) {
        return $scope.authData = authData;
    });
}]);

我不确定这是否有效,但似乎不是因为我收到此错误:

Error: [$injector:unpr] http://errors.angularjs.org/1.3.10/$injector/unpr?p0=%24scopeProvider%20%3C-%20%24scope%20%3C-%20shared
at Error (native)
at https://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js:6:417
at https://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js:38:307
at Object.d [as get] (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js:36:308)
at https://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js:38:381
at d (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js:36:308)
at e (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js:37:64)
at Object.instantiate (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js:37:213)
at Object.<anonymous> (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js:37:490)
at Object.e [as invoke] (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js:37:96)

我是这样注入的:

flickrApp.controller('tagsCtrl', ['$scope', '$firebase', 'shared', function($scope, $firebase, shared) {

    console.log($scope.authData.uid); //This would come from the 'shared' service now
}]);

这里有什么问题?

【问题讨论】:

    标签: angularjs angularfire rootscope


    【解决方案1】:

    上面的answer 解释了为什么它(可能)不起作用,但我建议您以不同的方式解决您的问题(在控制器之间共享变量)。

    您应该改为创建一个服务(类似于“shared”)并以这种方式共享数据。这是可行的,因为服务是单例的,而控制器不是。此外,您不会将变量添加到您的根作用域中,即使您不需要它们也会随身携带。

    查看此类共享服务的一个很好的示例检查here.

    这是我的示例,应该适用于您的示例:

    首先是共享服务:

    flickrApp.service('shared', function() {
    
        var authentication = 'none';
    
        return {
            getAuth: function () {
                    return authentication;
            },
            setAuth: function (auth) {
                authentication = auth;
            }
        };
    });
    

    我喜欢保持此共享服务的所有逻辑干净,并且仅将其用于共享数据。

    接下来是主控制器,您必须确保在登录后调用任何其他控制器之前实际调用它(因此您将把它放在处理登录的控制器中!)

    flickrApp.controller('mainCtrl', ['$scope', '$firebase', 'shared', 'Auth', function($scope, $firebase, Auth, shared) {
    
        Auth.$onAuth(function(authData) {
            shared.setAuth(authData);
            console.log(shared.getAuth()); //Check if it was set correctly
        });
    }]);
    

    最后是需要检查登录状态的任何其他控制器:

    flickrApp.controller('tagsCtrl', ['$scope', '$firebase', 'shared', function($scope, $firebase, shared) {
        $scope.auth = shared.getAuth();
        if($scope.auth === 'none'){
          console.log('you are not logged in!');
        }else{
            console.log('welcome '+$scope.auth.uid);
            //anything you would do if a user is logged in
        }
    }]);
    

    我假设您知道以下内容,但我只想重复一遍(我不熟悉 firebase):

    请始终注意,恶意用户可能会操纵 javascript 代码,请确保在向服务器发送的每个 http 请求中都发送用户令牌,以确保用户实际登录并且不依赖 javascript为你做这件事。

    如果您有任何其他问题,请告诉我。

    【讨论】:

    • 我试过了,但我在某处失败了。看看更新的问题。
    • 由于某种原因,我什至无法将服务注入到控制器中...... 精神抖擞。
    • 我编辑了我的初始回复,如果您仍然无法添加服务,请告诉我,您可能忘记将其添加到您的 index.html 作为参考。
    • 现在看来可以了,感谢您抽出宝贵时间帮助我,非常感谢。 :)
    • 好的,很高兴听到这个消息; Angular 有时会很困难:D
    【解决方案2】:

    这是一个通过共享服务和范围共享数据的简单示例

    js

    (function(app) {
    
        function SharedService() {
            this.user = {};
        }
    
        function Controller1(scope, SharedService) {
            scope.sharedService = SharedService;
        }
    
        function Controller2(scope, SharedService) {
            scope.sharedService = SharedService;
        }
    
        app.service('SharedService', SharedService);
        app.controller('Controller1', Controller1);
        app.controller('Controller2', Controller2);
    
    })(angular.module('myApp', []));
    

    html

    <script src="https://code.angularjs.org/1.3.4/angular.js"></script>
    <script type="text/javascript" src="js/exp2/app.js"></script>
    <div ng-app="myApp">
        <div ng-controller="Controller1 as ctrl">
            </br> 
            <table>
                <tr>
                    <td><B> Enter Age in Controller1</B></td>
                    <td><input type="text" ng-model="ctrl.userAge"></select></td>
                </tr>
            </table>
        </div>
        <div ng-controller="Controller2 as ctrl">
            <table>
                <tr>
                    <td><B> Age in controller2 : </B></td>
                    <td>{{ctrl.userAge}}</td>
                </tr>
            </table>
        </div>
    </div>
    

    请参阅以下链接以了解如何在不使用任何范围的情况下共享数据。 http://plnkr.co/edit/den1mfMeIAWezLTuVZVX?p=preview

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-15
      相关资源
      最近更新 更多