Reputation: 493
Hey Im trying to use google maps within my MeteorJS project to have google maps display on a map all customers, and then to display an infoWindow when you click on one of the markers.
problem is anytime you click on the marker it re-renders the map from scratch, i know this has to do with the the reactivity of the Session variable being set when the infoWindow is being clicked.
is there any way avoid the map being re-rendered when the session variable is changing?
thanks.
below is the JS and template im using in my project.
<template name="customers_map">
{{#constant}}
<div id="mapWrapper">
<div id="map-canvas"></div>
</div>
{{/constant}}
</template>
the code for making the google maps and markers.
Template.customers_map.rendered = function() {
$("#map-canvas").height("400px");
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(p) {
Session.set("myLat", p.coords.latitude);
Session.set("myLng", p.coords.longitude);
});
}
Deps.autorun(function(){
var mapOptions = {
center: new google.maps.LatLng(Session.get("myLat"), Session.get("myLng")),
zoom: 15,
zoomControl: true,
zoomControlOptions: {style: google.maps.ZoomControlStyle.SMALL},
streetViewControl: false,
mapTypeControl: false,
scaleControl: true,
mapTypeId: google.maps.MapTypeId.SMALL
}
var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
var infowindow = new google.maps.InfoWindow({
content: Template.customers_infoWindow()
});
Customers.find().forEach(function(customer) {
if (customer.loc != null) {
var geo = customer.geoLocation();
var marker = new google.maps.Marker({
position: new google.maps.LatLng(geo.lat, geo.lng),
title: customer.name(),
icon:'http://maps.google.com/mapfiles/ms/icons/green-dot.png'
});
marker.setMap(map);
google.maps.event.addListener(marker, 'click', function() {
Session.set("customerId", customer._id);
infowindow.open(map,marker);
});
} else {
console.log(customer.name() + " has no geoLocation");
};
});
});
};
the infoWindow template
<template name="customers_infoWindow">
<h1>{{record.name}}</h1>
</template>
and the js for the infoWindow template
Template.customers_infoWindow.record = function() {
return Customers.findOne({_id: Session.get("customerId")});
}
Upvotes: 0
Views: 839
Reputation: 380
If you create a global googlemaps object, you can access its properties from anywhere. This article has a nice example of doing this. The overall gist is:
Upvotes: 1
Reputation: 8013
It's a bit difficult to be sure without having a running version in front of me, but I think this is essentially because you have all your code in one big Deps.autorun
block. Clicking one of the markers is changing the Session variable customerId
, which will cause customers_infoWindow
to re-render (as it's clearly a dependency), but I'm sure this is the intended behaviour.
However, since you're declaring var infoWindow
in your Deps.autorun
block to have an instance of that template as one of its properties, I think that changing customers_infoWindow
will actually invalidate the entire Deps.autorun
calculation, which means the whole block will be executed again, including the var map = new google.maps.Map(...)
line, which will essentially re-render the map (even though it doesn't re-render that actual div element that contains it).
So, I would suggest splitting your code into separate Deps.autorun
blocks, and making sure that anything in the same block should be re-run at the same time - clearly, this means that the Google Maps initialisation code and the infoWindow
handler should be in separate blocks.
To reiterate, I think that's what's going on, but you'll have to try it and let me know...
Upvotes: 0