Search code examples
angularjsgoogle-mapsangularjs-google-maps

Google Maps not working in AngularJS directive


I am the creator of ng-map.

I´m trying to develop a directive in AngularJS to show a Google Maps. I can show the map, but I want to go one step further. My directive will accept coords or an address. In case the coords are set, it will show a marker with them. However if the coords are not available, then it should try to show a marker using the address and Geocode.

My problem is when I try to run the geocode function inside the directive, this request looks asynchronous and the rest of the code is executed before I get the response.

How can I force to execute this request?

Please see my plunker: http://plnkr.co/edit/QRj6jXQYxSRR3CseavQY?p=preview

<div class="span12">

    {{center}}
    <label>Address</label>
    <input type="text" ng-model="completeAddress" class="input-xxlarge input-height-large" placeholder="Type your business address...">     
    <map id="map_canvas" style="height: 452px; margin-bottom: 20px;"></map> 

    <button class="btn btn-primary btn-large pull-right" style="margin-bottom: inherit" ng-click="setBusinessLocation()">Save</button>  
</div>

You can notice, there is a marker in one city (Gijon) (after geocode), but the map is created before with the center in other city (Getafe).

Thanks, Roberto.


Solution

  • To resolve the issue,

    1. From directive, pass map to controller for the map access.
    2. Create GeoCoder as a service using $q, and $rootScope.$apply for async. processing
    3. Use GeoCoder from controller, and if required from your map directive as the form of GeoCoder(address).then(...) to show marker when geocode lookup is done

    This is the service part.

    app.service('GeoCoder', function($q, $rootScope) {
        return {
          getLocations : function(address) {
            var deferred = $q.defer();
            var geocoder = new google.maps.Geocoder();
            console.log('address', address);
            geocoder.geocode({'address': address }, function (results, status) {
              $rootScope.$apply(function() {
                if (status == google.maps.GeocoderStatus.OK) {
                  deferred.resolve(results);
                }
              });
            });
            return deferred.promise;
          }
        }
    });
    

    and this is function to add marker from address in controller

      $scope.addMarkerFromAddress = function() {
        GeoCoder.getLocations($scope.address).then(function(results) {
          var latLng = results[0].geometry.location;
          var marker = new google.maps.Marker({
            map: $scope.map, 
            position: latLng
          });
          $scope.map.setCenter(latLng);
        });
      };
    

    And finally, this is demo, http://plnkr.co/edit/9gkanMqVZCldZjYZ5oA2?p=preview