0

I want my $http response data to be available to the controller, so as to display JSON data in the view via directive ("{{ hint }}"). However, while, in the controller, I can log data from the factory, the data will not provide itself in a useable manner.

When what is provided by the factory is logged in the controller, it is either "undefined" or "not a function". From the code below, "undefined" is logged"

Please, help me right my wrongs? How do I clean this up, so as to use factory's .GET data in the controller?

Controller:

var MainCtrl = angular.module('MainCtrl', []);

MainCtrl.controller('Ctrl2', [ "QuizViewServ", '$log', '$scope',
function(QuizViewServ, $log, $scope){


 $scope.init = function(){
    $scope.hint = "FooBar";  //Testing binding bw Ctrl2 & the view
    $log.log(QuizViewServ.getQuizData.quizQz); // <-LOGS AS "UNDEFINED"
 }

}]);

Factory:

var MainServ = angular.module('MainServ', []);

MainServ.factory('QuizViewServ', ['$http', function($http){
 console.log("factory working");

 var getQuizData = function(){

   $http({
      method: 'GET',
      url: '/assets/json.json'
    }).then(function successCallback(response) {
        console.log("inside successgul GET req");


        var quizQz;
        quizQz = response.data.quizQs;
        console.log(quizQz);


    }, function errorCallback(response) {

        alert("Trouble grabbing requested data.")
    });
  }
  return {
    getQuizData : getQuizData
  }

}]);
Erik_K
  • 3
  • 3

2 Answers2

1

$http uses promises to return the result. When using QuizViewServ.getQuizData.quizQz you are logging nothing, since its asynchronous.

In your factory, return the promise, and in you controller, handle it.

var MainServ = angular.module('MainServ', []);

MainServ.factory('QuizViewServ', ['$http', function($http){
 console.log("factory working");

 var getQuizData = function(){

   return $http({
      method: 'GET',
      url: '/assets/json.json'
    })
  }
  return {
    getQuizData : getQuizData
  }

}]);

and in your controller

var MainCtrl = angular.module('MainCtrl', []);

MainCtrl.controller('Ctrl2', [ "QuizViewServ", '$log', '$scope',
function(QuizViewServ, $log, $scope){


 $scope.init = function(){
    $scope.hint = "FooBar";  //Testing binding bw Ctrl2 & the view

    QuizViewServ.getQuizData().then(function(result){
        $log.log(result.data);
    });
 }

}]);
Andrew Donovan
  • 552
  • 2
  • 14
  • this does work. And for exactly the reasons you mentioned above, which I neglected. HOWEVER, doesn't this mean that the "business logic", of iterating through objects of the JSON file, has to stay in the Controller? For the sake of "cleanliness", should that logic be kept in the Service? ---I'm not disputing your answer, I'm genuinely curious. – Erik_K May 13 '16 at 13:09
  • It depends if you need to do different treatments with the returned data. If it is somewhat unique for every controller that uses it, you should do it within the controller. If multiple controller needs the same data, then do your data treatment in the factory using @Zohaib Ijaz 's solution, they are both valid :P So basically, you have the option of doing both ways, depends on the scenario and your personal preference – Andrew Donovan May 13 '16 at 13:13
  • Gotcha. That totally makes sense. Yes, I've tried yours and @Zohaib Ijaz ' solutions. They both work, as you said, in diff circumstances. Thanks. – Erik_K May 13 '16 at 13:32
  • Glad we could help ! Please mark one of the answers as correct for other user's visiting this question later on – Andrew Donovan May 13 '16 at 13:33
0

You need to retrun that data. It is not possible as you are doing. Also quizQz propert is private. You can not access it even after that value has been set after ajax call.

var getQuizData = function(){

return $http({
  method: 'GET',
  url: '/assets/json.json'
}).then(function successCallback(response) {
    console.log("inside successgul GET req");


    var quizQz;
    quizQz = response.data.quizQs;
    console.log(quizQz);
    return quizQz;

  }, function errorCallback(response) {

    alert("Trouble grabbing requested data.")
    return '';
});

}

and in controller , get data like this.

QuizViewServ.getQuizData().then(function(data){
    console.log(data);
});
Zohaib Ijaz
  • 21,926
  • 7
  • 38
  • 60
  • You can't return data in a promise, You need to assign it to a variable that is declared outside of that promise, or return the object to handle the promis. My answer is the proper way to retrieve data from a promis. Return the function that returns the promis and handle it. : http://stackoverflow.com/questions/26854654/get-data-out-of-a-promise-instead-of-returning-a-promise – Andrew Donovan May 12 '16 at 19:55
  • I am using angular in my production app and I know ,we can return data , however I missed to add return statement before $http() – Zohaib Ijaz May 12 '16 at 19:58
  • Then you would have to $watch the result from `getQuizData ()` that seems like bad practice if its the case, im curious as to how you do it – Andrew Donovan May 12 '16 at 20:00
  • No, no need to watch. I don't want to say that, learn first .. let me give you a refrence – Zohaib Ijaz May 12 '16 at 20:02
  • @AndrewDonovan, Look at this, if this is wrong , he can not get 337 up votes. Confirm first before rejecting someone's answer. http://stackoverflow.com/a/12513509/5567387 – Zohaib Ijaz May 12 '16 at 20:05
  • Yes, you are right. I didn't realize that returning within a promise allows your to change the returned value. I first downvoted your answer because you were missing a return statement. Will upvote back, thanks for sharing the knowledge. – Andrew Donovan May 12 '16 at 20:10
  • @AndrewDonovan Thank you for that.. but don't down vote without serious reasons and proof. – Zohaib Ijaz May 12 '16 at 20:12
  • @ZohaibIjaz Thanks. Both yours and Andrew's solution work. And the link to "Processing $http response in service" thread was very helpful. Thank ya! – Erik_K May 13 '16 at 13:32