binoculars
binoculars

Reputation: 2274

Google maps and asynchronous javascript

In my controller, I have this function to get the coordinates of an address:

function get_coor(city, callback)
{
    var geocoder = new google.maps.Geocoder();
    geocoder.geocode( { "address": city }, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK && results.length > 0) {
            var location = results[0].geometry.location;
            callback(location.lat(), location.lng());
            }
            else
{
            callback(); // callback for error
    }
            });
            }

Doing this works fine and outputs the correct latitude:

get_coor('Amsterdam', function(lat, lng) {
    console.log('here is my lat:' + lat);
});

I want to use these coordinates in my google map, so I made it like this:

get_coor('Amsterdam', function(lat, lng) {
    $scope.map = {center: {latitude: lat, longitude: lng }, zoom: 4 };
    $scope.options = {scrollwheel: false};
    $scope.marker = {
        coords: {
            latitude: lat,
            longitude: lng
        },
        show: false,
        id: 0
    };

    $scope.windowOptions = {
        visible: false
    };

    $scope.onClick = function() {
        $scope.windowOptions.visible = !$scope.windowOptions.visible;
    };

    $scope.closeClick = function() {
        $scope.windowOptions.visible = false;
    };
});

The map is centered correctly, so $scope.map = {center: {latitude: lat, longitude: lng }, zoom: 4 }; seems to work fine, but the marker is placed on it's default location, not Amsterdam. When I view the source, the coordinates of the marker are the right coordinates.

My guess is that it has something to do with asynchronous javascript, but I'm very new to this... Anyone who can help?

UPDATE:

Refreshing the page puts the marker on the right position, but it persists on first load.

Upvotes: 2

Views: 174

Answers (1)

Vadim Gremyachev
Vadim Gremyachev

Reputation: 59348

Since geocoder.geocode function executes asynchronously and ui-gmap-marker is a child directive, you should call $apply() explicitly in that case:

$scope.marker = {
      coords: {
        latitude: location.lat(),
        longitude: location.lng()
      },
      title: 'Amsterdam',
      show: true,
      id: 1
};


$scope.$apply();

Working example

var appMaps = angular.module('appMaps', ['uiGmapgoogle-maps']);
appMaps.controller('mainCtrl', function ($scope, uiGmapGoogleMapApi, uiGmapIsReady) {
  $scope.windowOptions = {
    visible: false
  };

  $scope.onClick = function () {
    $scope.windowOptions.visible = !$scope.windowOptions.visible;
  };

  $scope.closeClick = function () {
    $scope.windowOptions.visible = false;
  };

  $scope.options = { scrollwheel: false };


  $scope.map = { center: { latitude: 30, longitude: 0 }, zoom: 4 };



  var resolveAddress = function (address, callback) {
    var geocoder = new google.maps.Geocoder();
    geocoder.geocode({ "address": address }, function (results, status) {
      if (status == google.maps.GeocoderStatus.OK && results.length > 0) {
        var location = results[0].geometry.location;
        callback(location);
      }
      else {
        callback(null);
      }
    });
  }


  uiGmapGoogleMapApi.then(function (gapi) {

    resolveAddress('Amsterdam', function (location) {

      $scope.$apply(function () {
        $scope.map.center = { latitude: location.lat(), longitude: location.lng() };

        $scope.marker = {
          coords: {
            latitude: location.lat(),
            longitude: location.lng()
          },
          title: 'Amsterdam',
          show: true,
          id: 1
        };
      });

    });

  });


});
.angular-google-map-container {
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    left: 0;
}
<script src="https://code.angularjs.org/1.3.14/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>
<script src="http://rawgit.com/angular-ui/angular-google-maps/2.0.X/dist/angular-google-maps.js"></script>

<div ng-app="appMaps" id="map_canvas" ng-controller="mainCtrl">
	<ui-gmap-google-map center="map.center" zoom="map.zoom" draggable="true" options="options" bounds="map.bounds">
		<ui-gmap-marker idkey="marker.id" coords="marker.coords" options="marker.options" click="onClick()" events="marker.events" />
	</ui-gmap-google-map>
</div>

Upvotes: 1

Related Questions