Saving an $http response object as a $scope variable

All we need is an easy explanation of the problem, so here it is.

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.

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

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 */);
    };
}) ;

Method 2

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.

Method 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

Method 4

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

Method 5

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!

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply