[SOLVED] GoogleMap need refresh in FlowRouter

I have a template to show the Google Map Geolocation. When I declare the template inside the body the map shows immediately.

<head>    
    <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=false"></script>
</head>

<body>
{{> geolocation}}
</body>

My problem now if I call the template inside my FlowRouter, it does not show my map and need to refresh it in order to show the map.

FlowRouter.route('/geo', {
   name:"geo",
  action: function(params) {
   FlowLayout.render("geolocation");
  }
});

Can someone help me identify what is causing this problem. Thanks.

1 Like

Someone can help me with this?

Hi there,

Can you include the contents of your geolocation helper? That will make it easier to debug. You might try this though:

<template name="mainLayout">
  {{> Template.dynamic template=main}}
</template>

FlowRouter.route('/geo', {
   name:"geo",
  action: function(params) {
   FlowLayout.render("mainLayout", { main: "geolocation" });
  }
});

@levid i tried putting my geolocation template inside my mainLayout before but the result is the same.

Here’s my Template.geolocation helper

Template.geolocation.onCreated(function() {
 var pos;
  function initialize() {
    var mapOptions = {
      zoom: 14,
      styles: [{
        "featureType": "water",
        "stylers": [{
          "saturation": 43
        }, {
          "lightness": -11
        }, {
          "hue": "#0088ff"
        }]
      }]
    };
    // map = new google.maps.Map(document.getElementById('map-container'), mapOptions);
    map = new google.maps.Map($('#map-container')[0], mapOptions);
    // Try HTML5 geolocation
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(function(position) {
        pos = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
        Session.set("setLat", position.coords.latitude);
        Session.set("setLng", position.coords.longitude);
        var botikaMarker = {
          url: 'images/mobotika.png',
        };

        var markerUser = new google.maps.Marker({
          animation: google.maps.Animation.DROP,
          position: pos,
          map: map,
          icon: botikaMarker
        });

        map.setCenter(pos);
      }, function() {
        handleNoGeolocation(true);
      });
    } else {
      // Browser doesn't support Geolocation
      handleNoGeolocation(false);
    }
  } //initialize

  function handleNoGeolocation(errorFlag) {
    if (errorFlag) {
      var content = 'Error: The Geolocation service failed.';
    } else {
      var content = 'Error: Your browser doesn\'t support geolocation.';
    }

    var options = {
      map: map,
      position: new google.maps.LatLng(10.310014, 123.893131),
      content: content
    };

    var infowindow = new google.maps.InfoWindow(options);
    map.setCenter(options.position);
  };

  google.maps.event.addDomListener(window, 'load', initialize);

});

If you don’t mind using a few packages to make things more Meteor friendly, here is a working solution:

  • Install the dburles:google-maps package for reactive google map
    support.
  • Install the mdg:geolocation package for reactive geolocation support.
  • Create a startup.js file in your client folder and paste this code in it:
if (Meteor.isClient) {
  Meteor.startup(function() {
    // Potentially prompts the user to enable location services. We do this early
    // on in order to have the most accurate location by the time the user shares
    Geolocation.currentLocation();
    GoogleMaps.load();
  });
}
  • Updated geolocation.js file:
Template.geolocation.onCreated(function(){
  // We can use the `ready` callback to interact with the map API once the map is ready.
  GoogleMaps.ready('newMap', function(map) {
    Tracker.autorun(function(){
      var lat = Session.get('lat');
      var lng = Session.get('lng');
      var error = Geolocation.error();
      // Detect any geolocation errors
      if(error){
        handleNoGeolocation(map.instance, error);
      }
      // Render the map
      else {
        // Define a custom marker
        var botikaMarker = { url: 'images/mobotika.png' };
        // Store map position
        var pos = new google.maps.LatLng(lat, lng);
        // Center the map to the new coordinates
        map.instance.setCenter(pos);
        // Add a marker to the map once it's ready
        var marker = new google.maps.Marker({
          animation: google.maps.Animation.DROP,
          position: pos,
          map: map.instance,
          icon: botikaMarker
        });
      }
    });
  });
});
Template.geolocation.helpers({
  mapOptions: function(){
    var lat, lng, location, options;
    // Make sure the maps API has loaded
    if (GoogleMaps.loaded()) {
      location = Geolocation.currentLocation();
      // Check if location contains any coordinates
      if(location && location.coords){
        lat = location.coords.latitude;
        lng = location.coords.longitude;
      } 
      // Otherwise use a default location
      else {
        lat = 10.310014;
        lng = 123.893131;
      }
      // Define reactive variables
      Session.set('lat', lat);
      Session.set('lng', lng);
      // Map initialization options
      options = {
        center: new google.maps.LatLng(lat, lng),
        zoom: 8,
        styles: [{
          "featureType": "water",
          "stylers": [{
            "saturation": 43
          }, {
            "lightness": -11
          }, {
            "hue": "#0088ff"
          }]
        }]
      };
      return options;
    }
  }
});
// Handle any Geolocation errors
function handleNoGeolocation(mapInstance, error) {
  var options = {
    map: mapInstance,
    position: new google.maps.LatLng(10.310014, 123.893131),
    content: error
  };
  var infowindow = new google.maps.InfoWindow(options);
  mapInstance.setCenter(options.position);
};

You should see your default map at first just like in your example. If any Geolocation error occurs, it should display the info window you had in there as well. When any new Geolocation coordinates are detected, the Tracker.autorun will kick in and reactively center the map to the new position.

  • Updated geolocation.html file:
<template name="geolocation">
  <div class="map-container">
    {{> googleMap name="newMap" options=mapOptions}}
  </div>
</template>
  • Updated geolocation.css file:
.map-container {
  width: 800px;
  max-width: 100%;
  height: 500px;
}

I hope this helps !

1 Like

it works!.. I did not know that you can actually use the two packages together and it’s really neat now.
here’s for your help :coffee: :relaxed:

Glad to hear you got it working :smile:

If you want to get even fancier with it, @dburles just posted a great tutorial in this thread that goes into even more detail.

I saw @dburles post 2 hours after I read your reply and I smiled =)

I’ve had a few people asking about doing geolocation so I figured I’d do a post :slight_smile: