0

I am trying to use an $http promise from a factory withing my controller. Code below works, and I can view the users variable in the view by calling {{users}}

Working Factory:

.factory('bidsCreatedSimple', ['$http', function($http) {
    // Expose public API first, use func notation
      return { 
          getUsers: getUsers,
      };

      function getUsers(){
          return $http.get('/bids.json');
      }
}])

In the controller:

$scope.users = []; //visible in the view

activate();

function activate(){
    bidsCreatedSimple.getUsers().then(function(users){
      $scope.users = users.data;
    });
} 

console.log($scope.users); //returns a blank [] even though
                           //it renders with data in the view

How can I use the $scope.users variable in my controller? I need to use it's data for some other objects in the controller.

Gonzalo.-
  • 12,512
  • 5
  • 50
  • 82
GavinBelson
  • 2,514
  • 25
  • 36

1 Answers1

2

your code is fine. $scope.users DOES get filled with data, but your console.log($scope.users) is executed before the $http request returns - therefore you're console.logging the empty array you declare at the top of your code.

add the console.log line in the callback and you'll see your users (assuming data is returning correctly from your backend)

bidsCreatedSimple.getUsers().then(function(users){
      $scope.users = users.data;
      // here $scope.users is filled with the .json data
      console.log($scope.users)
      // put here your code to manipulate users (or call a function that does that properly)
    });
// here the $scope.users is undefined, because when this line executes, the request from get users hasn't returned yet (and the callback function hasn't executed either)
console.log($scope.users)

This is due to asynchrony in the ajax request - you need to wait for data until the request returns in order to use it.

Gonzalo.-
  • 12,512
  • 5
  • 50
  • 82
  • Right, but I have a bunch of objects in the controller that use `$scope.users`. For example `$scope.gridOptions.data` needs to be set to `$scope.users` in order for a library to render a grid. How would I set those variables to the users data? – GavinBelson Mar 02 '17 at 02:44
  • are you using angular-ui ? I haven't used it, but you probably can set the reference to $scope.users, and then use some refresh method or something similar. Like http://stackoverflow.com/questions/26634063/how-to-use-refresh-method-in-ui-grid – Gonzalo.- Mar 02 '17 at 02:48
  • But, how would I actually use that data in the controller? I need to pass it to some services as well, that will manipulate it – GavinBelson Mar 02 '17 at 02:51
  • just call your services using yourService($scope.users). But you need to be sure your request has returned, if not you will just pass an empty array. See my code where it says "put here code to manipulate users". If that's not what you're asking, then I don't understand your question. You might want to add some code about what you're trying to achieve. – Gonzalo.- Mar 02 '17 at 02:53
  • see my update. You might want to read something about asynchrony as well https://medium.freecodecamp.com/understanding-asynchronous-javascript-callbacks-through-household-chores-e3de9a1dbd04#.g6uwax9w2 – Gonzalo.- Mar 02 '17 at 02:55
  • I see what you're saying. But how would I make sure that the request has returned? The only way i've found so far is using chaining ` .then(function successCallback(response) {console.log($scope.filteredBids);});` to the activate() function – GavinBelson Mar 02 '17 at 02:59
  • yes, that's how you should do it. Chaining is the best way to achieve async functionality – Gonzalo.- Mar 02 '17 at 03:00
  • :( I see, is there another DRY option other than chaining? – GavinBelson Mar 02 '17 at 03:04
  • I don't see where's the repetition. Can you please update your code to see how it looks now ? – Gonzalo.- Mar 02 '17 at 03:06
  • I see, I just thought I could write it without waiting for callbacks every time. Your answer is correct. – GavinBelson Mar 02 '17 at 03:09