Не удается получить доступ к authData, привязанному к $rootScope, с одного из контроллеров

У меня есть ошибка, которая сводит меня с ума, в основном все, что я пытаюсь сделать, это установить $rootScope.authData свойство, которое содержит информацию аутентификации пользователя, чтобы я мог использовать ее в разных контроллерах.

Тем не менее, когда я пытаюсь это, это просто дает мне ошибку, говоря $rootScope.authData не определено. Я проверил, и это действительно определяется при входе в консоль из mainCtrl, но это undefined при входе в консоль из tagsCtrl,

Это странно, учитывая тот факт, что я могу использовать $rootScope.authData в одном из моих других контроллеров.. А также я, если я добавлю $rootScope.test = 'testing' в mainCtrl и консоль лог что в 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
}]);

Что здесь не так?

2 ответа

Решение

Приведенный выше ответ объясняет, почему он (возможно) не работает, но я бы порекомендовал вам решить вашу проблему (совместное использование переменных между контроллерами) другим способом.

Вместо этого вы должны создать сервис (что-то вроде "общего доступа") и таким образом обмениваться данными. Это работает, потому что сервисы являются синглетонами, а контроллеры - нет. Кроме того, вы не добавляете в корневую область переменные, которые будут переноситься, даже если они вам не нужны.

Чтобы увидеть хороший пример такого общего сервиса, проверьте здесь.

Вот мой пример, который должен работать для вашего примера:

Во-первых, общий сервис:

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 для этого для тебя.

Если у вас есть другие проблемы, пожалуйста, дайте мне знать.

Вот простой пример обмена данными через общий сервис и область

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

Другие вопросы по тегам