Chanon Deeprasertkul
Chanon Deeprasertkul

Reputation: 195

Return value in Javascript but it turns out to be undefined

I'm new at Javascripts and i'm trying to use Angular UI route, here is my code

myApp.config(['$stateProvider', '$urlRouterProvider',function($stateProvider, $urlRouterProvider) {     
    $stateProvider  
        .state('home', {
            url: '/test',
            templateUrl: '/custom.html'
        })
        .state('detail', {                
            url: '/{examID}',              
            views: {
            '': {
              templateUrl: '/templates/customize.html',
               controller: ['$scope', '$stateParams', 'utils',

                function ( $scope,$stateParams,utils) {
                  $scope.exam = utils.findById($stateParams.examID);
                  console.log('exam is ' + $scope.exam );
                }
                ]
        }            
            }
        }     )    

    }])

and this is the service which has findbyID function

angular.module('service', [])
.factory('utils', function ( $http) {
  return {
    findById: function findById(id) {
       $http.get('/api/exams/' + id).success(function(response) {
            return response;
    })}
};});

i've already follwed this topic but $scope.exam still undefined

How to return value from an asynchronous callback function?

PS. i've tried to print out response and it's an object

Thx

Upvotes: 1

Views: 83

Answers (3)

Shubham Nigam
Shubham Nigam

Reputation: 3954

Use deferred promise, So that it would return value after response

Service:

angular.module('service', [])
.factory('utils', function ( $http) {
  return {
    findById: function findById(id) {
       var promise=$http.get('/api/exams/' + id);
   return promise;
};});

Controller:

   myApp.config(['$stateProvider', 
  '$urlRouterProvider',function($stateProvider, $urlRouterProvider) {     
            $stateProvider  
                .state('home', {
                    url: '/test',
                    templateUrl: '/custom.html'
                })
                .state('detail', {                
                    url: '/{examID}',              
                    views: {
                    '': {
                      templateUrl: '/templates/customize.html',
                       controller: ['$scope', '$stateParams', 'utils',

                        function ($scope, $stateParams, utils) {
                                                   utils.findById($stateParams.examID).then(function(value) {
                        $scope.exam = value;
                        console.log('exam is ' + $scope.exam );
                         });

                        }
                        ]
                       }           
                    }
                })    
        }])

Upvotes: 0

James Brewer
James Brewer

Reputation: 1755

This is a place where a lot of developers new to JavaScript stumble.

What is going on here is that you are assigning the return value of utils.findById() to $scope.exam. The problem is that utils.findById() doesn't actually return anything. (When a function doesn't have an explicit return statement in JavaScript, the return value is implicitly undefined.)

Here is what your service should look like:

angular
  .module('service', [])
  .factory('utils', function ($http) {
    return {
      findById: function (id) {
        return $http.get('/api/exams/' + id);
      }
    };
  });

You probably noticed that the call to .success() has disappeared too! Don't worry. It just moved.

Instead of calling .success() on $http.get(), we want to call it on utils.findById(). Doing this will give you access to the response variable in your controller. Because you will have access to the response variable, you will be able to assign response to $scope.exam like so:

.state('detail', {
  url: '/{examID}',
  views: {
    '': {
      templateUrl: '/templates/customize.html',
      controller: ['$scope', '$stateParams', 'utils',
        function ($scope, $stateParams, utils) {
          utils.findById($stateParams.examID)
            .success(function (response) {
              $scope.exam = response;
            });
        }
      ]
    }
  }
});

Hopefully that cleared it up. If I haven't been clear on anything, please let me know so I can update this answer.

Upvotes: 1

Tarun Dugar
Tarun Dugar

Reputation: 8971

You have to wait for the ajax call to finish. Modify the code in your controller to:

$scope.exam;
utils.findById($stateParams.examID).then(function(data) {
    $scope.exam = data.data;
}

Read about the concept of 'Promises' in AngularJS and JavaScript.

Upvotes: 0

Related Questions