Reputation: 28338
I've got a bug which is driving me nuts, basically all I'm trying to do is to set a $rootScope.authData
property which holds a user's authentication information so that I can use it in different controllers.
However, when I try this it's just gives me an error saying $rootScope.authData
is not defined. I've checked and it is indeed defined when logging it to the console from the mainCtrl
, but it's undefined
when logging it to the console from the tagsCtrl
.
This is strange considering the fact that I can use the $rootScope.authData
in one of my other controllers.. And also I if I add $rootScope.test = 'testing'
in the mainCtrl
and console log that in the tagsCtrl
it works.
I can't see anything wrong that I've done here and I've reached a dead end. Any ideas?
Main controller which sets the $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
});
}]);
The controller that can't access the $rootScope.authData
:
flickrApp.controller('tagsCtrl', ['$scope', '$rootScope', '$firebase', function($scope, $rootScope, $firebase) {
console.log($rootScope.authData); //Is not defined here
}]);
EDIT: After some feedback from Bricktop I tried to create a service for this, which turned out like this:
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;
});
}]);
I'm not sure if this would be a valid one but it appears that it's not since I get this error:
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)
I inject it like this:
flickrApp.controller('tagsCtrl', ['$scope', '$firebase', 'shared', function($scope, $firebase, shared) {
console.log($scope.authData.uid); //This would come from the 'shared' service now
}]);
What's wrong here?
Upvotes: 1
Views: 767
Reputation: 1549
The above answer explains why it (probably) isn't working but I would recommend that you solve your problem (sharing variables between controllers) in a different manner.
You should instead create a service (something like "shared" ) and share data that way. This works because services are singletons while controllers are not. Additionally you don't add variables to your rootscope that will be carried around even if you don't need them.
To see a good example of such a shared service check here.
Here is my example that should work for your example:
Firstly the shared service:
flickrApp.service('shared', function() {
var authentication = 'none';
return {
getAuth: function () {
return authentication;
},
setAuth: function (auth) {
authentication = auth;
}
};
});
I like to keep this shared service clean from all logic and use it only for sharing data.
Next up is the main controller you have to make sure that this is actually called before any other controller is called after login ( So you would put it in a controller that handles logging in !)
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
});
}]);
Lastly any other controller that needs to check the logged in state :
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
}
}]);
I assume that you know the following but I am just going to repeat this (I am not familiar with firebase) :
Always be aware that javascript code could be manipulated from a malicous user, make sure you send a user token with every http request you send to your server to make sure that the user is actually logged in and don't rely on javascript to do this for you.
If you have any other problems, please let me know.
Upvotes: 1
Reputation: 1843
here is a simple example of sharing data through shared service and scope
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>
refer following link to know how to share data without using any sort of scope. http://plnkr.co/edit/den1mfMeIAWezLTuVZVX?p=preview
Upvotes: 0