0

My directive uses a service which returns a promise, I need to display the scope attributes geoZip, geoCity and geoState in the template.

The issue is that those scope variables are not being shown in the template, I just see the comma.

What should I do to make it display the scope variables?

This is my directive code:

  .directive('cityStateZip', function() {
      return {
        restrict: 'A',
        transclude: true,
        scope: {
          zip: '=',
        },
        template: '<p>{{geoCity}}, {{geoState}} {{geoZip}}</p>',
        controller: ['$scope', 'GeolocationService', function ($scope, GeolocationService) {
          GeolocationService.geocode($scope.zip).then(function(result) {
            if (result) {
              console.log(result);
              $scope.geoZip = result['address_components'][0]['long_name'];
              $scope.geoCity = result['address_components'][1]['long_name'];
              $scope.geoState = result['address_components'][2]['short_name'];
            }
          });
        }]
      };
    })

.service('GeolocationService', ['underscore', '$q', function (underscore, $q) {
  var gs = {};

  gs.geocode = function(address) {
    var geocoder = new google.maps.Geocoder();
    var deferred = $q.defer();
    geocoder.geocode( { "address": address }, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK && results.length > 0) {
        return deferred.resolve(underscore.first(results));
      }
      return deferred.reject();
    });
    return deferred.promise;
  }

  return gs;
}]);
16
  • 1
    Show the geocode() service function. Judging by property names it looks like you are using google...which is outside angular context and you will need $apply in there somewhere to tell angular to run a digest Commented Jan 4, 2016 at 1:52
  • yes, but how I should use the $apply method in my code? Commented Jan 4, 2016 at 1:53
  • 1
    Can use it in the service function ...in google geocode callback or in the controller. Curious though what promise is being returned Commented Jan 4, 2016 at 1:54
  • when I use the $scope.apply() just after the line which assigns $scope.geoState I get an error: "$digest already in progress". docs.angularjs.org/error/$rootScope/inprog?p0=$digest Commented Jan 4, 2016 at 1:57
  • 1
    put code in question where it can be formatted and read...not dumped into comment blocks Commented Jan 4, 2016 at 2:10

1 Answer 1

1

I found that I have to use the $timeout service to make it work:

.directive('cityStateZip', function() {
  return {
    restrict: 'A',
    transclude: true,
    scope: {
      zip: '=',
    },
    template: '<p>{{geoCity}}, {{geoState}} {{geoZip}}</p>',
    controller: ['$scope', '$timeout', 'GeolocationService', function ($scope, $timeout, GeolocationService) {
      GeolocationService.geocode($scope.zip).then(function(result) {
        if (result) {
          console.log(result);
          $timeout(function() {
            $scope.geoZip = result['address_components'][0]['long_name'];
            $scope.geoCity = result['address_components'][1]['long_name'];
            $scope.geoState = result['address_components'][2]['short_name'];
          });
        }
      });
    }]
  };
})

Please let me know if there is best alternative (not using $timeout), Thanks!

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

1 Comment

$timeout is recommended by the AngularJS authors as the best way to do a "safe $apply". The GeolocationService is asynchronous to the AngularJS digest cycle. $timeout gives the browser a chance to catch up and sync back with the digest cycle.

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.