I'm developing an app (in my local machine) which displays various locations (an array that varies in size) in an accordion. I'm using the accordion and pagination directives from Angular UI Bootstrap with the Google Maps JS API-based directives from Angular Google Maps.
I have an issue where sometimes the map loads in the first item I clicked, then I click on another item in the accordion and the map doesn't load. Then a few minutes later, I'll refresh my browser and I click on the same item and the map will load. Then if I go to another page in the pagination, the maps aren't displayed there. As you can see in my code, I'm only calling the maps when I click on an item in the accordion, not when the items are loaded. I don't want a lot of maps to be loaded right away if the size of the locations array is large.
Here is a plunker demonstrating the problem, and here is a fiddle.
Here is some code from the example linked above which I think is important to the problem:
HTML body
<accordion close-others="oneAtATime">
<accordion-group is-open="status.open" ng-repeat="location in locations | startFrom: (currentPage-1)*5| limitTo: 5">
<accordion-heading >
<strong get-map-dir location-index={{$index}}>Location</strong> - {{location.address1}}
</accordion-heading>
<div id="branch_map" class="" ng-show="showMap ">
<ui-gmap-google-map center='location.mapInfo.map.center' zoom='location.mapInfo.map.zoom'>
<ui-gmap-marker coords="location.mapInfo.marker.coords" options="location.mapInfo.marker.options" idkey="location.mapInfo.marker.id">
<ui-gmap-window ng-cloak closeClick="closeClick()">
</ui-gmap-window>
</ui-gmap-marker>
</ui-gmap-google-map>
</div>
</accordion-group>
<pagination total-items="locations.length" items-per-page="itemsPerPage" ng-model="currentPage" ng-change="pageChanged()" ng-hide="locations.length < itemsPerPage"></pagination>
</accordion>
JS (partial)
.factory('anotherService', function() {
//getMap using google-maps directive from angularjs-ui
var getMap = function(locationObj, outerCallBack) {
console.info('get map');
var mapInfo = {};
var address = locationObj.address1;
var zoom = 16;
var geocoder = new google.maps.Geocoder();
console.log(locationObj);
geocoder.geocode({
"address": address, //required
"region": 'CA' //CA for canada
}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK && results.length > 0) {
var location = results[0].geometry.location,
lat = location.lat(),
lng = location.lng();
mapInfo.map = {
center: {
latitude: lat,
longitude: lng
},
zoom: zoom
};
mapInfo.marker = {
id: 0,
coords: {
latitude: lat,
longitude: lng
},
options: {
title: address
}
};
outerCallBack({
success: true,
mapInfo: mapInfo
});
} else if (status === google.maps.GeocoderStatus.ZERO_RESULTS) {
console.info("Geocoder was sucessful but has no results");
console.info("address =" + address);
return;
} else if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
console.error("You are over your query limit");
console.info("address =" + address);
return;
} else if (status === google.maps.GeocoderStatus.REQUEST_DENIED) {
console.error("Your request has been denied by Geocoder");
return;
} else if (status === google.maps.GeocoderStatus.INVALID_REQUEST) {
console.error("Invalid Geocoder request");
return;
} else {
console.error("Google Maps in Ctrl failed");
console.error("address =" + address);
return;
}
});
};
var anotherService = {
getMap: getMap
};
return anotherService;
})
.directive('fetchMap', function($timeout, anotherService) {
return {
restrict: 'A',
link: function(scope, elem, attrs) {
console.log("get map dir");
console.log(scope);
console.log(elem);
console.log(attrs);
elem.bind('click', function(event) {
// console.clear();
console.log("You clicked on me");
console.log(scope.locations[attrs.locationIndex].mapInfo);
if (angular.isUndefined(scope.locations[attrs.locationIndex].mapInfo)) {
anotherService.getMap(scope.locations[attrs.locationIndex], function(callBackfunc) {
console.info("Getting maps");
// scope.showPreloader = false;
scope.locations[attrs.locationIndex].mapInfo = callBackfunc.mapInfo;
$timeout(function() {
scope.showMap = true;
}, 2000);
});
}
});
}
};
})