Angularjs not storing variable to $scope after AJAX call within $http.get request
Asked Answered
N

3

5

I'm using angularjs and I can't get the following controller to save to a $scope variable the data returned from an AJAX request to Flickr. The $http.get makes a call to a locally saved json file. Upon success, it uses the json returned in success() to determine the appropriate url for the AJAX call to the Flickr API. Upon success of that call, I log the data to the console. So far so good, it returns an array of three objects. However, I'm trying to set that array to a $scope variable ($scope.photos) so I can iterate over it my view template. However, when I try outputing {{photos}} in the html there is nothing. I suspect this is a promise issue, and the template is rendering before the AJAX returns the data from Flickr, but I've been pouring over the docs with no success (looked at $q a little). I'm somewhat new to Angular and would appreciate your insight. Thanks!

artistControllers.controller('PhotoController', ['$scope', '$http', '$routeParams', '$q', function ($scope, $http, $routeParams, $q){
  $http.get('js/data.json').success(function(data){
    $scope.artists = data;
    $.ajax({
         type : "GET",
         dataType : "jsonp",
         url : $scope.artists[$routeParams.itemId].flickr,
         success: function(flickr){
            $scope.photos = flickr.items;
            console.log($scope.photos);
         }
    }); 
  });
}]);
Nutriment answered 19/11, 2014 at 3:37 Comment(3)
Why use jQuery instead of $http?Ragamuffin
A valid question @Phil, see below for similar comments. Short answer is I haven't been able (yet) to successfully call Flickr without $.ajax.Nutriment
Here is an answer that might help your flickr issue: #20721047Fronton
N
1

Thank you everyone for your help and feedback. I have found a solution using $q and $http.jsonp, in part thanks to this tutorial:

http://youtu.be/gApduktFwxw?t=17m

Here is my code, note that my API url string to flickr has &jsoncallback=JSON_CALLBACK appended to it:

$http.get('js/data.json').success(function(data){
    $scope.artist = data[$routeParams.itemId];
    var url =  $scope.artist.flickr;
    console.log(url);

    $scope.init = function(){
        $scope.getImages()
        .then(function(res){
            console.log(res);
        }, function(status){
            console.log(status);
        });
    };

    $scope.getImages = function(){
        var defer = $q.defer();

        $http.jsonp(url)
            .success(function(res){
                defer.resolve(res);
                console.log(res);
            }).error(function(status, err){
                defer.reject(status);
                console.log(err);
            });

        return defer.promise;           
    };

    $scope.init();
Nutriment answered 25/11, 2014 at 0:20 Comment(0)
F
8

Don't use jQuery.ajax. Angular's $http can do JSONP too. You can read more about here.

artistControllers.controller('PhotoController', ['$scope', '$http', '$routeParams', '$q', function ($scope, $http, $routeParams, $q){
  $http.get('js/data.json').success(function(data){
    $scope.artists = data;
    $http.jsonp($scope.artists[$routeParams.itemId].flickr).success(function(data){
        $scope.photos = flickr.items;
        console.log($scope.photos);
    });
  });
}]);
Fronton answered 19/11, 2014 at 3:46 Comment(2)
I am looking into $http.jsonp, but I have not yet been able to make it work whereas $.AJAX does. Will continue to strive for pure Angular implementation.Nutriment
Here's a random jsfiddle that demonstrates how to use it: jsfiddle.net/subhaze/a4Rc2/114Fronton
P
7

Because you are executing code outside of Angular's knowledge, you need to manually call $scope.$digest() for it to "see" your change and update the markup accordingly.

Just change your success handler to:

 success: function(flickr){
    $scope.photos = flickr.items;
    $scope.$digest();
 }

Note: $scope.$apply() would also work, because it does a $digest of every single scope in your application, starting from the $rootScope down. On a big application, this can be much slower than necessary, so in your case I recommend only digesting from the scope you are modifying down.

Photostat answered 19/11, 2014 at 3:43 Comment(3)
This is not ideal. You shouldn't have to manually call $digest. $http does this for you.Fronton
Correct. I should have mentioned that it would be better to use the Angular $http service instead. But if you have to use the jQuery .ajax() method, then you do need to do $scope.$digest() yourself.Photostat
The way which I was looking for. It just solved the issue thanks.Ingeborg
N
1

Thank you everyone for your help and feedback. I have found a solution using $q and $http.jsonp, in part thanks to this tutorial:

http://youtu.be/gApduktFwxw?t=17m

Here is my code, note that my API url string to flickr has &jsoncallback=JSON_CALLBACK appended to it:

$http.get('js/data.json').success(function(data){
    $scope.artist = data[$routeParams.itemId];
    var url =  $scope.artist.flickr;
    console.log(url);

    $scope.init = function(){
        $scope.getImages()
        .then(function(res){
            console.log(res);
        }, function(status){
            console.log(status);
        });
    };

    $scope.getImages = function(){
        var defer = $q.defer();

        $http.jsonp(url)
            .success(function(res){
                defer.resolve(res);
                console.log(res);
            }).error(function(status, err){
                defer.reject(status);
                console.log(err);
            });

        return defer.promise;           
    };

    $scope.init();
Nutriment answered 25/11, 2014 at 0:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.