Gly Jones
Gly Jones

Reputation: 99

AngularJS: How to block execution until function returns?

I'm trying to display a google map on click with angular JS. But my function seems to be toggling the visibility based on a function call (via ng-show). This means that my trigger of the 'resize' event executes before the map div is actually visible so it doesn't work correctly.

$scope.mapVisible = false;
$scope.toggleMap = function() {
    $scope.myMap.panTo($scope.myMarkers[0].getPosition());
    $scope.mapVisible = !$scope.mapVisible;
    // this executes too soon. How to block until the div is really visible?
    google.maps.event.trigger($scope.myMap, 'resize');
}

<div ng-show="mapVisible">
   <!-- map here -->
</div>

So how can I block triggering the 'resize' event on my map until the div is truly visible?

Upvotes: 1

Views: 1393

Answers (2)

Scott Coates
Scott Coates

Reputation: 2512

I figured the easiest case is to use the $timeout service:

scope.$on "map:ui:shown", (event, args)->
    $timeout ->
      #use a delay because most of the time, the resizing should occur immediately after an angular cycle
      #like when an ng-show has been set to the True condition
      googleMaps.event.trigger(map, 'resize')
      map.fitBounds scope.bounds if scope.bounds

Upvotes: 0

Umur Kontacı
Umur Kontacı

Reputation: 35478

$scope.$watch("mapVisible", function (val) {
  if (val) {
    google.maps.event.trigger($scope.myMap, "resize");
  }
});

This would make sure the map is visible before triggering the event.
Angularjs handles two-way binding by doing dirty-checking. It basically means that the value being watched is compared to the one in previous cycle. Each cycle ($digest) starts to run when something happens which could possibly change any value in the scope. If there is a change in the value, it would be reflected after the cycle has completed.

Back to your problem, when you toggle the mapVisible property, the view does not update immediately. It waits for the cycle to end before redrawing the view. But you fire the resize event so early, when the map is still invisible, therefore rendering invalid.

$watch does indeed watch the property and the changes will be reflected in the next cycle of the change, which means the view would be updated by the time watcher function has been invoked. Putting the resize function here would hence solve your issue.

Upvotes: 1

Related Questions