Не удается получить доступ к 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