0

I try to play with bootstrap typeahead and angular. When current method was in controller - all worked fine:

$scope.getLocation_work = function(val) {
    return $http.get('http://maps.googleapis.com/maps/api/geocode/json', {
      params: {
        address: val,
        sensor: false
      }
    }).then(function(res){
      var addresses = [];
      angular.forEach(res.data.results, function(item){
        addresses.push(item.formatted_address);
      });
      return addresses;
    });
  };

When I tried to put the logic into service, I started get errors:

ypeError: Cannot read property 'length' of undefined

in controller

$scope.getLocation = function(val) {
            UtilsFactory.getLocation(val).then(function(res){
                var addresses = [];
                angular.forEach(res, function(item){
                    addresses.push(item.formatted_address);
                });
                return addresses;
            });
        };

Service

app.factory('UtilsFactory', ['$http', '$q', function($http, $q) {
                return {
                    getLocation : function(val) {
                          var deferred = $q.defer();
                          var response = $http.get('http://maps.googleapis.com/maps/api/geocode/json', {
                params: {
                    address: val,
                    sensor: false
                }
            });

             deferred.resolve(response);
               return deferred.promise;
                }      
       }
  }
]);

Do I miss something?

Here is Demo in Plunker

Thanks,

1 Answer 1

1

There were 2 problems in your plunker:

(1) For whatever reason you were writing $http promise callback differently when called from a controller and differently when a promised was returned from the service. But promise hitting a backend is the same promise with the same results so it should be handled the same:

        $scope.getLocation = function(val) {
            return UtilsFactory.getLocation(val).then(function(res){
                var addresses = [];
                angular.forEach(res.data.results, function(item){
                    addresses.push(item.formatted_address);
                });
                return addresses;
            });
        };

On top of this you were missing the return in the $scope.getLocation function!

(2) $http already works with promises so there is no need to use $q on top of it. You can write your service as simply as:

app.factory('UtilsFactory', ['$http', function($http) {
  return {
    getLocation : function(val) {
        return $http.get('http://maps.googleapis.com/maps/api/geocode/json', {
          params: {
            address: val,
            sensor: false
          }
        });
    }
  };
}]);

Finally a fixed plunk: http://plnkr.co/edit/hG5iHWfGq3QNAp6J8YSW?p=preview

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, I thought I can wrap anything (sync/async) with deferred so I generate new promise. Actually I get the list from my service and its populated right but somehow fails to update bootstrap. Again Thanks,
How about using typeahead-input-formatter="formatLabel($model)" to display the label and save the value for model? Actually I am loading ajax content with label, id pairs of json. I need to show the label, but need to store id in the database.The issue was already reported in GitHub

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.