All, I have the following AngularJS below. Why is $scope.gotData
not visible outside of the call to getData.success()
? Note that $scope.gotData
is visible to the view: I can display the value of scope.gotData
by placing {{gotData}}
within my index.html
.
Why can I not access $scope.gotData
as a variable elsewhere in my controller? This is a question concerning the details of $scope.
getData.js
myApp.factory('getData',function($http){
return $http.jsonp('https://foo.com/bar.json')
.success(function(data){
return data;
})
.error(function(err){
return err;
});
});
MainController.js
myApp.controller('MainController', ['$scope','getData', function($scope, getData){
getData.success(function(data){
$scope.gotData = data;
});
$scope.gotData /* NOT DEFINED HERE */
}]);
index.html
<html>
<head>
<script src="js/vendor/angular.js"></src>
</head>
<body ng-app="MyApp">
<div ng-controller="MainController">
{{gotData}} /* I CAN SEE THE DATA HERE */
</div>
</body>
</html>
The reason why you cannot see $scope.gotData
outside the getData.success()
function is because .success()
is async and the value is not available when you try to access it outside .success()
. This essentially means that the promise has not been resolved yet.
Moreover, once angular's digest cycle identifies that $scope.gotData
is populated, it quickly updates the view. Thats the reason why you can see $scope.gotData
in the view
Things would be more clear once you put a watch
on $scope.gotData
myApp.controller('MainController', ['$watch','$scope','getData', function($watch,$scope, getData){
getData.success(function(data){
$scope.gotData = data;
});
$scope.$watch($scope.gotData,function(n,o){
console.log("new val-> "+n);
console.log("old val->"+o);
})
}]);
the call to getData.success is asynchronous. So before executing that success function, your call to console of $scope.gotData is done. So you are supposed to define a default value of this $scope.gotData beforehand. And when you get a success call, only then you should use it. Something like this :
myApp.controller('MainController', ['$scope','getData', function($scope,getData){
$scope.gotData = null;
getData.success(function(data){
$scope.gotData = data;
});
if($scope.gotData != null)
// Do something useful with this data
}]);
Although not the best programming practice, but a solution to this is to use $rootScope.
myApp.controller('MainController', ['$scope','getData', function($scope, getData){
getData.success(function(data){
$rootScope.gotData = data;
});
console.log($rootScope.gotData) // this will be accessible across
// different controllers aswell
}]);