Search code examples
javascriptangularjsgoogle-mapsjavascript-objectsgoogle-geocoder

Google Maps Geocode AngularJS ignores callback


I have got a strange problem with the JavaScript Geocode Api of Google Maps in AngularJS.

First of all I did some researches and I find out that I have to use the javascript callback function to get the formatted address out of a coordinate.

I implemented the callback function like this:

"use strict";

var getParcelApp = angular.module("getParcelApp", []);

function getStartAddress(latlng, callback) {
    var geocoder = new google.maps.Geocoder;

    geocoder.geocode({ 'location': latlng }, function(results, status) {
        if (status === google.maps.GeocoderStatus.OK) {
            callback(results[2].formatted_address); // HERE THE CALLBACK
        }
    });
};

var GetParcelAppController = function($scope, $http) {
    $http.get("/umbraco/surface/ParcelSurface/GetLatLngParcel")
        .success(function(result) {
            $scope.coordinates = result;
            $scope.getStartCoordinate();
        })
        .error(function(data) {
            console.log(data);
        });

    $scope.getStartCoordinate = function() {
        var latlng;

        $scope.listOfCoordinates = [];

        for (var i = 0; i < $scope.coordinates.length; i++) {
            latlng = { lat: $scope.coordinates[i].Latitude, lng: $scope.coordinates[i].Longitude };

            getStartAddress(latlng, function(formattedAddress) {
                console.log(formattedAddress); // HERE formattedAddress WORKS
                var coordinate = {
                    id: $scope.coordinates[i].Id,
                    waypointId: $scope.coordinates[i].WaypointId,
                    latitude: $scope.coordinates[i].Latitude,
                    longitude: $scope.coordinates[i].Longitude,
                    address: formattedAddress // HERE formattedAddress ISN'T WORKING
                };
                $scope.listOfCoordinates.push(coordinate);
            });
        }
        console.log($scope.listOfCoordinates);

    };
};

getParcelApp.controller("getParcelAppCtrl", GetParcelAppController);

As you may see I want an array of coordinate objects. But I really don't know why the console.log shows the right result and array is complete empty?

The Firefox console shows the following:

  • The Array:
    • Array [ ] getParcelController.js:45:9
  • The formatted addresses:
    • Mitte, Berlin, Deutschland getParcelController.js:34:17
    • Innenstadt, Köln, Deutschland getParcelController.js:34:17
    • Altstadt-Lehel, München, Deutschland getParcelController.js:34:17
    • Mitte, Berlin, Deutschland getParcelController.js:34:17
    • Innenstadt, Köln, Deutschland getParcelController.js:34:17

Do you have an idea why the console log is working properly and the array function isn't? If I write the array function outside of the callback function and without address: the array is created.

To be more detailed:

I want to show the formatted addresses of the coordinates in a select drop down box. This is defined in a html file as

<select id="getParcel" class="form-control"></select>

and i edited the getStartAddress call like the following:

$scope.getStartCoordinate = function() {
    var latlng;
    var selectBox = document.getElementById("getParcel");

    $scope.listOfCoordinates = [];

    for (var i = 0; i < $scope.coordinates.length; i++) {
        latlng = { lat: $scope.coordinates[i].Latitude, lng: $scope.coordinates[i].Longitude };

        getStartAddress(latlng, function(formattedAddress) {
            var coordinate = {
                id: $scope.coordinates[i].Id,
                waypointId: $scope.coordinates[i].WaypointId,
                latitude: $scope.coordinates[i].Latitude,
                longitude: $scope.coordinates[i].Longitude,
                address: formattedAddress
            };
            $scope.listOfCoordinates.push(coordinate);
            console.log($scope.listOfCoordinates);

            var selectElement = document.createElement("option");
            selectElement.textContent = coordinate.address;
            selectElement.value = coordinate.address;

            selectBox.appendChild(selectElement);
        });
    }

};

I am really not an expert in javascript but in my understanding the function in getStartAddress is then called when the callback data are fetched? So the select drop down box should be filled with the addresses when the callback is finished, isn't it?


Solution

  • Okay I solved that problem with a forEach instead of the simple for loop.

    So the result is the following:

    "use strict";
    
    var getParcelApp = angular.module("getParcelApp", []);
    
    function getStartAddress(latlng, callback) {
        var geocoder = new google.maps.Geocoder;
    
        geocoder.geocode({ 'location': latlng }, function(results, status) {
            if (status === google.maps.GeocoderStatus.OK) {
                callback(results[2].formatted_address);
            }
        });
    };
    
    var GetParcelAppController = function($scope, $http) {
        $http.get("/umbraco/surface/ParcelSurface/GetLatLngParcel")
            .success(function(result) {
                $scope.coordinates = result;
                $scope.getStartCoordinate();
            })
            .error(function(data) {
                console.log(data);
            });
    
        $scope.getStartCoordinate = function() {
            var latlng;
            var selectBox = document.getElementById("getParcel");
    
            $scope.listOfCoordinates = [];
    
            $scope.coordinates.forEach(function(point) {
                latlng = { lat: point.Latitude, lng: point.Longitude };
    
                getStartAddress(latlng, function (formattedAddress) {
                    var coordinate = {
                        id: point.Id,
                        waypointId: point.WaypointId,
                        latitude: point.Latitude,
                        longitude: point.Longitude,
                        address: formattedAddress
                    };
                    $scope.listOfCoordinates.push(coordinate);
    
                    var selectElement = document.createElement("option");
                    selectElement.textContent = formattedAddress;
                    selectElement.value = formattedAddress;
    
                    selectBox.appendChild(selectElement);
                });
            });
        };
    };
    
    getParcelApp.controller("getParcelAppCtrl", GetParcelAppController);