Reputation: 3707
I am using ionic to display benefits data on Google map. It works fine except on click of any marker, it opens the last markup content. Follownig is my google map js code
.controller('BenefitsMapCtrl', function ($scope, LocationBenefits, Utilities, $ionicLoading, $compile) {
$scope.init = function () {
var userId = Utilities.getUserId();
LocationBenefits.getLocationBenefits(userId, function (userBenefits) {
console.log("Got location benefits data for Google mp for user id "+userId);
$scope.userBenefits = userBenefits;
var centerLatlng;
if (typeof $scope.userBenefits !== "undefined" && $scope.userBenefits.length > 0) {
var firstBenefitLocation = $scope.userBenefits[0];
centerLatlng = new google.maps.LatLng(firstBenefitLocation.location.lat, firstBenefitLocation.location.lng);
}
var mapOptions = {
center: centerLatlng,
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
$scope.markers=[];
//Loop in each benefits and place on Google map
if (typeof $scope.userBenefits !== "undefined" && $scope.userBenefits.length > 0) {
for (var i = 0; i < $scope.userBenefits.length; i++) {
var benefit = $scope.userBenefits[i];
//Marker + infowindow + angularjs compiled ng-click
var contentString = "<div><div><img class='shop-icon' src='" + benefit.shopicon + "' alt='" + benefit.shopName + "'/><span class='item-text-wrap'>" + benefit.shopName + "</span></div><div class='shop-offer'>"+benefit.benefits.short_benefitText+"</div><div class='card'><img class='card-art' src='"+benefit.cardart+"' alt='"+benefit.card+"'/></div></div>";
var compiled = $compile(contentString)($scope);
var infowindow = new google.maps.InfoWindow({
content: compiled[0]
});
//Get location
var locationLatLng = new google.maps.LatLng(benefit.location.lat, benefit.location.lng);
var marker = new google.maps.Marker({
position: locationLatLng,
map: map,
title: benefit.shopName
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker);
});
$scope.markers.push(marker);
}
}
//Finally set the map
$scope.map = map;
});
};
// google.maps.event.addDomListener(window, 'load', initialize);
$scope.centerOnMe = function () {
if (!$scope.map) {
return;
}
$scope.loading = $ionicLoading.show({
content: 'Getting current location...',
showBackdrop: false
});
navigator.geolocation.getCurrentPosition(function (pos) {
$scope.map.setCenter(new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude));
$scope.loading.hide();
}, function (error) {
alert('Unable to get location: ' + error.message);
});
};
$scope.clickTest = function () {
alert('Example of infowindow with ng-click')
};
});
Issue: On click of any markup on Google map, it always opens the last markup. Please help.
Upvotes: 0
Views: 1451
Reputation: 488
I had the same problem and spend a lot of time to figure out what's going on so I'd like to add the answer for the future generations,lol.
First of all it's a good idea to refer to official Google maps API docs and take a look at "Events section". I found there one interface of adding event listeners to markers that I never seen before(even after googling this issue for few hours).
marker.addListener('click', function() {});
google.maps.event.addListener(marker, 'click', function () {});
It pointed me out to the idea that when you are trying to do it in the loop using an "old" way, your marker variable is obviously equals to the last element of your markers array. And when event really can be triggered your initialization process is finished what means that your variable has always wrong value in anonymous function at the moment it can be really called. So, again, you didn't passed marker
as a parameter to that anonymous event handler.
But you still can do what you want. Just use this.
inside your event handler. Bellow is my code sample
marker.addListener('click', function() {
var it = this;
$scope.$apply(function() {
$scope.activeEvent = EventService.getShort($scope.events[it.id]);
});
});
I believe that you can try to use this.
in "old-style" interface as well.
Upvotes: 1
Reputation: 13
I had the same problem and I found the solution here. Apparently, you just have to create a function to create the markers and call that function inside the for loop:
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
$scope.map = map; //Attach the map to the scope before adding the markers
$scope.markers=[];
var infowindow = new google.maps.InfoWindow();
var createMarkers = function (benefit){
//Info window's content
var contentString = "<div><div><img class='shop-icon' src='" + benefit.shopicon + "' alt='" + benefit.shopName + "'/><span class='item-text-wrap'>" + benefit.shopName + "</span></div><div class='shop-offer'>"+benefit.benefits.short_benefitText+"</div><div class='card'><img class='card-art' src='"+benefit.cardart+"' alt='"+benefit.card+"'/></div></div>";
var compiled = $compile(contentString)($scope);
//Get location
var locationLatLng = new google.maps.LatLng(benefit.location.lat, benefit.location.lng);
//Create marker
var marker = new google.maps.Marker({
position: locationLatLng,
map: map,
title: benefit.shopName
});
google.maps.event.addListener(marker, 'click', function () {
infoWindow.setContent(compiled[0]);
infoWindow.open($scope.map, marker);
});
$scope.markers.push(marker);
}
//Loop in each benefits and place on Google map
if (typeof $scope.userBenefits !== "undefined" && $scope.userBenefits.length > 0) {
for (var i = 0; i < $scope.userBenefits.length; i++) {
var benefit = $scope.userBenefits[i];
createMarkers(benefit);
}
}
Upvotes: 0