5

I asked a related question earlier today on stackoverflow but due to both the complexity of the code (not being able to post it) and my own noviceness I wasn't able to really implement a solution from the answers given.

So my question now is, for a code such as:

$http.get(ArbitraryInput).then(function (response) {$scope.data = response});

(you can substitute "then" with "success" above, I use "then" because success is deprecated according to the updated $http api)

How do I actually save the response object in $scope.data? From what I've been doing so far, $scope.data is "undefined" when I later typed in the code:

console.log($scope.data3);

Thanks!

UPDATE ONE

Apparently if I put console.log($scope.data); inside the console will display what I want for $scope.data. But if it is outside, it will remain "undefined" in the console. In other words:

$http.get(ArbitraryInput).then(function (response) {$scope.data = response; console.log($scope.data);});

will return whatever sort of object response was. in the console, but

$http.get(ArbitraryInput).then(function (response) {$scope.data = response;});
console.log($scope.data);

will return "undefined" in the console.

Vivz
  • 6,625
  • 2
  • 17
  • 33
LargeCrimsonFish
  • 233
  • 2
  • 7
  • 15
  • 1
    $http.get($scope.coveragesDEMO).then(function (response) {$scope.data = response.data}); Can you check it out? – Danny Fardy Jhonston Bermúdez Oct 02 '15 at 17:34
  • Thanks for the response. I tried it and it didn't work. console.log(response.data) is undefined, whereas console.log(response) is still defined. console.log($scope.data) is still undefined in all scenarios – LargeCrimsonFish Oct 02 '15 at 17:39
  • 1
    Can you post the response you get? – Aakash Oct 02 '15 at 17:41
  • 1
    The `console.log` executed outside the *then* is executed before the assignment in the *then* callback, that's why it outputs *undefined* – Michel Oct 02 '15 at 17:46
  • Ah, that makes sense. So that's why console.log needs to be executed inside the then; but is there any way to set a $scope variable to the response and have it persist outside the then? Cause if I was trying to use $scope.data as the input for another http.get, I wouldn't have to put it inside the first http.get's 'then'. – LargeCrimsonFish Oct 02 '15 at 17:50
  • 1
    The response may log as `undefined` because it is not set until your GET response is received. However, it will be set when you get the data, and hence available in your controller and view. – show-me-the-code Oct 02 '15 at 17:51

5 Answers5

6

You need to leverage the fact that $http.get returns a promise, and chain to that promise in any code that needs to access the resolved data:

app.controller('Ctrl', function($scope, mainInfo){
    var request = $http.get(ArbitraryInput).then(function (response) {
        $scope.data = response; 
        return response; // this will be `data` in the next chained .then() functions
    });

    request.then(function (data) {/* access data or $scope.data in here */});


    $scope.someFunction = function () {
        request.then(function (data) {/* access data or $scope.data in here */);
    };
}) ;
William B
  • 1,411
  • 8
  • 10
5

Question has been answered, but want to give an alternate solution in case the data is needed immediately. Instead of calling the $http service directly in your controller/directive, you can resolve that data as a dependency in your route, so the data is immediately availble:

angular.module('myApp')
    .config(['$routeProvider', function($routeProvider) {
        $routeProvider.when('/home', {
            templateUrl: '/path/to/template',
            controller: 'myCtrl',
            controllerAs: 'ctrl',
            resolve: {
                myData: ['$http', function($http) {
                    return $http.get('/end/point');
                }
            }
        }
    }]);

Then your controller can look like this:

angular.module('myApp')
    .controller('myCtrl', ['myData', function(myData) {
        var self = this;
        self.data = myData;
    }]);

And in your view:

<pre>{{ctrl.data|json:4}}</pre>

Would display all of your data as JSON without having to call $http in your controller.

Caleb Williams
  • 1,035
  • 5
  • 12
3

Try this:

$http.get(ArbitraryInput).then(function (response) {
    $scope.data =     response;
    console.log($scope.data);
});

$http.get is asynchronous. See also this explanation of AJAX

Community
  • 1
  • 1
Thierry
  • 5,133
  • 3
  • 25
  • 30
  • Thank you for your response. I tried that and it did provide what I wanted in the console, however I'm still trying to figure out how to set a controller $scope variable to permanently be the response from the object. Any reference to the variable outside of the function seems to return an "undefined". – LargeCrimsonFish Oct 02 '15 at 17:48
  • LargeCrimsonFish, the references outside the function need to WAIT until the $http.get is resolved before accessing the $scope variable. – William B Oct 02 '15 at 17:57
  • @LargeCrimsonFish, You can watch what is actually happening to your $scope object by running a $scope.$watch method and logging out the data. So $scope.$watch('data', function(newValue, oldValue) { console.log(newValue, oldValue);}); and you will see that the $scope.data value is only updated after the $http call is resolved, but will be bound to your view as soon as it can. If you want to perform some operation on that data, you have to do that after the resolve (inside some other function/service). If you need that data immediately, look at the resolve attribute in your routes. – Caleb Williams Oct 02 '15 at 18:01
2

Please note that this is a promise (async request) so if you did something like this

$http.get(ArbitraryInput).then(function (response) {$scope.data = response;});
console.log($scope.data)

it might log nothing ,, as you try to log it before the request is finished so you might need to use something like this

$http.get(ArbitraryInput).then(function (response) {
$scope.data = response;
console.log($scope.data);
});

so you are sure that console.log will be executed after the assignment to $scope.data

Ahmed Eid
  • 1,145
  • 8
  • 9
  • Yeah you're right. I didn't realize it was an asynchronous operation cause I'm still pretty new to this. In that case would it be possible to do something like $http.get().then(dothisfirst).then(dothisafter) – LargeCrimsonFish Oct 02 '15 at 17:56
  • I can't understand ,, what you want to do ?? before and after what ?? – Ahmed Eid Oct 02 '15 at 18:05
  • LargeCrimsonFish, see my answer for setting the scope variable on resolution and then accessing it from other functions in the controller. – William B Oct 02 '15 at 18:09
1

Here is a practical answer, courtesy of user Kirill Slatin. Practical use example at the bottom of the answer.

If, like me, you need to use that response object as a scope variable, here's the trick:

This will return "undefined" in the console, and like me, you probably won't be able to use that response data on your page:

$http.get(ArbitraryInput).then(function (response) {$scope.data = response;});
console.log($scope.data);

However, this should work:

    $http.get(ArbitraryInput)
         .then(function (response) {
            $scope.data = response;
            $scope.$apply()
});

$scope.$apply() is what will persist the response object so you can use that data.

-

Why would you need to do this?

I'd been trying to create an "edit" page for my recipes app. I needed to populate my form with the selected recipe's data. After making my GET request, and passing the response data to the $scope.form, I got nothing... $scope.$apply() and Kirill Slatin helped big time. Cheers mate!

Here's the example from my editRecipeController:

  $http.get('api/recipe/' + currentRecipeId).then(
    function (data) {
      $scope.recipe = data.data;
      $scope.form = $scope.recipe;
      $scope.$apply()
    }
);

Hope that helps!

Community
  • 1
  • 1
Bptstmlgt
  • 128
  • 1
  • 12