0

I have an application that uses an AngularJS service and using Angular-Google-Maps and I do get multiple markers on my map but I can't get the click on each marker to work. The only marker that allows a click is the last one which doesn't allow me to close it after opening the window or if I only have one address the marker works as expected. I think I'm close but can't figure out what I might be missing to have the click on the markers work for all of them. Any ideas on what I'm missing or need to do differently?

Here is the markup on my page.

<div ng-app="myMapApp" ng-controller="mapController">    
<ui-gmap-google-map center='map.center' zoom='map.zoom' options="options">        
    <ui-gmap-markers models="directoryMarkers" coords="'self'" icon="'icon'" click="'onClick'">
        <ui-gmap-windows show="show">
            <div ng-non-bindable>{{organization}}</div>
        </ui-gmap-window> 
    </ui-gmap-markers>
</ui-gmap-google-map>
</div>

The code in myMapApp.js

var app = angular.module("myMapApp", ['uiGmapgoogle-maps', 'ngStorage']);

The code in mapController.js

app.controller('mapController', function ($scope, Geocoder) {

$scope.map = { center: { latitude: 45, longitude: -73 }, zoom: 10 };

var hfValue = $("#ucDirectory_UcResults_hfResults");

$scope.directoryMarkers = [];

var createMarker = function (organization, address, latitude, longitude, i) {

    var ret = {
        latitude: latitude,
        longitude: longitude,
        address: address,
        organization: organization,
        show: false
    };

    ret.onClick = function () {
        console.log("Clicked!");
        ret.show = !ret.show;
    };

    ret["id"] = i;
    return ret;
};

var json = jQuery.parseJSON(hfValue[0].value);

var markers = [];
var i = 0;

var org;

for (var key in json) {
    if (json.hasOwnProperty(key)) {

        org = json[key].organization;



        if (json[key].address.length > 0) {

            Geocoder.geocodeAddress(json[key].address).then(function (data) {

            markers.push(createMarker(org, json[key].address, data.lat, data.lng, i))

            $scope.map.center.latitude = data.lat;
            $scope.map.center.longitude = data.lng;

            });

            i++;
        }
    }
}

$scope.directoryMarkers = markers;


});

The code in geocoder-service.js

 * An AngularJS Service for intelligently geocoding addresses using Google's API. Makes use of
 * localStorage (via the ngStorage package) to avoid unnecessary trips to the server. Queries
 * Google's API synchronously to avoid `google.maps.GeocoderStatus.OVER_QUERY_LIMIT`.
 *
 * @author: benmj
 * @author: amir.valiani
 *
 * Original source: https://gist.github.com/benmj/6380466
 */

/*global angular: true, google: true, _ : true */

'use strict';

//angular.module('geocoder', ['ngStorage']).factory('Geocoder', function ($localStorage, $q, $timeout, $rootScope) {
app.factory('Geocoder', function ($localStorage, $q, $timeout, $rootScope) {
    var locations = $localStorage.locations ? JSON.parse($localStorage.locations) : {};

    var queue = [];

    // Amount of time (in milliseconds) to pause between each trip to the
    // Geocoding API, which places limits on frequency.
    var QUERY_PAUSE = 250;

    /**
     * executeNext() - execute the next function in the queue.
     *                  If a result is returned, fulfill the promise.
     *                  If we get an error, reject the promise (with message).
     *                  If we receive OVER_QUERY_LIMIT, increase interval and try again.
     */
    var executeNext = function () {
        var task = queue[0],
          geocoder = new google.maps.Geocoder();

        geocoder.geocode({ address: task.address }, function (result, status) {

            if (status === google.maps.GeocoderStatus.OK) {

                var parsedResult = {
                    lat: result[0].geometry.location.lat(),
                    lng: result[0].geometry.location.lng(),
                    formattedAddress: result[0].formatted_address
                };
                locations[task.address] = parsedResult;

                $localStorage.locations = JSON.stringify(locations);

                queue.shift();
                task.d.resolve(parsedResult);

            } else if (status === google.maps.GeocoderStatus.ZERO_RESULTS) {
                queue.shift();
                task.d.reject({
                    type: 'zero',
                    message: 'Zero results for geocoding address ' + task.address
                });
            } else if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
                if (task.executedAfterPause) {
                    queue.shift();
                    task.d.reject({
                        type: 'busy',
                        message: 'Geocoding server is busy can not process address ' + task.address
                    });
                }
            } else if (status === google.maps.GeocoderStatus.REQUEST_DENIED) {
                queue.shift();
                task.d.reject({
                    type: 'denied',
                    message: 'Request denied for geocoding address ' + task.address
                });
            } else {
                queue.shift();
                task.d.reject({
                    type: 'invalid',
                    message: 'Invalid request for geocoding: status=' + status + ', address=' + task.address
                });
            }

            if (queue.length) {
                if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
                    var nextTask = queue[0];
                    nextTask.executedAfterPause = true;
                    $timeout(executeNext, QUERY_PAUSE);
                } else {
                    $timeout(executeNext, 0);
                }
            }

            if (!$rootScope.$$phase) { $rootScope.$apply(); }
        });
    };

    return {
        geocodeAddress: function (address) {
            var d = $q.defer();

            if (_.has(locations, address)) {
                d.resolve(locations[address]);
            } else {
                queue.push({
                    address: address,
                    d: d
                });

                if (queue.length === 1) {
                    executeNext();
                }
            }

            return d.promise;
        }
    };
});

1 Answer 1

2

As an aside, if you don't have a lot of windows open at the same time, you shouldn't use the windows directive, instead use the window directive and define it as a sibling to your markers. As recommended by the documentation.

But to answer the original question, this plnkr uses your code, minus the geocoding, to produce markers with windows. It takes two clicks on a marker to get to where you want it to be because the click happens before the value is changed.

I think to get the behavior you want it would look more like the following:

html:

<ui-gmap-google-map center='map.center' zoom='map.zoom' options="options">        
<ui-gmap-markers fit="true" models="directoryMarkers" coords="'self'" icon="'icon'" click="'onClick'">
</ui-gmap-markers>
<ui-gmap-window show="selected.show" coords="selected">
        <div>{{selected.organization}}</div>
</ui-gmap-window> 

controller:

  $scope.map = {
    center: {
      latitude: 45,
      longitude: -73
    },
    zoom: 10
  };

  $scope.directoryMarkers = [];
  $scope.selected = null;

  var createMarker = function(latitude, longitude, i) {

    var ret = {
      latitude: latitude,
      longitude: longitude,
      organization: "Foo",
      show: false
    };

    ret.onClick = function() {
      console.log("Clicked!");
      $scope.selected = ret;
      ret.show = !ret.show;
    };

    ret["id"] = i;
    return ret;
  };

  var markers = [];

  var org;

  var coords = chance.coordinates().split(",");
  $scope.map.center.latitude = coords[0];
  $scope.map.center.longitude = coords[1];
  for (var i = 0; i < 20; i++) {
    coords = chance.coordinates().split(",");
    markers.push(createMarker(coords[0], coords[1], i));
  }

  $scope.directoryMarkers = markers;

Which can be seen tied together in this plnkr: http://plnkr.co/edit/rT4EufIGcjplgd8orVWu?p=preview

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

1 Comment

Yip I had the same problem and it was because I was using 'windows' instead of 'window' ... wasted half a day on this problem

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.