Reputation: 170
Hi everyone I am an absolute newbie to frontend development and it is my first time to use something like AngularJS, tbh I think it is really difficult and I don't really have a lot of clear idea about how it works. I am working on a project that aims to visualize a batch of coordinates on Google Map. I have already built the corresponding API at the server-side and it works fine.
I'm using ng-map in my project and below is the first version of my code of main.html:
<div class="screen-wrapper" id="map-wrapper">
<div map-lazy-load="https://maps.google.com/maps/api/js">
<ng-map center="37.782551, -122.445368" zoom="3" disable-default-u-i="true">
<heatmap-layer id="foo" data="dummyData"></heatmap>
</ng-map>
</div>
</div>
The dummyData above is a hard-coded array in an external JS file which I originally thought unnecessary, but later when I tried to get the heatmapLayer from the map I found this was very important. Without this attribute I couldn't get the heatmapLayer in my controller. That was a bit odd, but I just don't know why it is like that.
Below is my main.controller.js:
(function() {
'use strict';
angular
.module('webapp')
.controller('MainController', MainController);
/** @ngInject */
function MainController(NgMap, $scope, $http) {
var resp = $http.get('url.to.api')
.then(function(result) {
return result.data;
});
var incidentData = []
var extractor = Promise.resolve(resp).then(function(data) {
for (var i = 0; i < data.length; i++) {
var lat = data[i]["lat"];
var lon = data[i]["lon"];
incidentData.push(new google.maps.LatLng(lat,lon));
}
}).then(function() {
var incidentArray = new google.maps.MVCArray(incidentData);
var heatMapLayer = new google.maps.visualization.HeatmapLayer({
data: incidentArray,
radius: 20
});
var heatmap;
$scope.$on('mapInitialized', function(event, map) {
heatMapLayer.setMap(map.instance);
});
});
}
})();
What I am trying to do above is to do a HTTP request to get the latitudes and longitudes back. Since it is in the format of "Promise", I have to extract them and put it into an array. Everything seems look okay to me, but it is simply not working. The interface only displays the 'hard-coded' visualization but not the new heatMapLayer.
Can anyone please suggestion the direction/solution to fix the problem I stated above? Thanks everyone and StackOverflow.
update After Daniel's advice I have made the following modification to my code.
In main.controller.js I changed the code segment:
$scope.$on('mapInitialized', function(event, map) {
heatMapLayer.setMap(map.instance);
});
to:
$scope.$apply(function() {
$scope.$on('mapInitialized', function(event, map) {
heatMapLayer.setMap(map.instance);
});
});
Again, thanks Daniel!
Upvotes: 1
Views: 1588
Reputation: 81
You are probably bypassing the digest cycle of angular. Meaning your changes are done already, but they don not display yet.
Angular keeps track of all the changes by itself, updating the view when something changes. Whenever you change something manually, not tracked by angular (e.g. tracked through ng-bind, or variables in {{ }}), you need to call scope.$apply() in order to trigger the digest cycle manually. Normally, you do not even notice (or need to know), when angular does this automatically. $http for example will take care of that too.
However, here
var resp = $http.get('url.to.api')
.then(function(result) {
return result.data;
});
I suspect scope.$digest() gets already called after the callback (at that time you did not change anything yet).
var extractor = Promise.resolve(resp).then(function(data) {
In your second .then() callback, you do your changes, but they will not be displayed anymore.
I would suggest to put the code from below into the first .then() callback. If this is not possible, you will have to call scope.$apply() manually after your changes are done.
Upvotes: 1