Accessing JavaScript map variable in Rails template for marker centering

I’m working on a Rails app with a Google Map and markers. The map works fine on the index page. I’m showing info for the last 5 markers in a sidebar using a partial called _timeline.

When I click an item in the sidebar, I want to center the map on that marker. Right now, it reloads the whole map, which isn’t what I want.

Here’s what I’ve got:

# index.html.erb
<div class="row">
  <% @recent_posts.each do |post| %>
    <%= render partial: "posts/summary", locals: { post: post } %>
  <% end %>
</div>

<script>
var mapHandler = Gmaps.build('Google');
mapHandler.buildMap({
  provider: { disableDefaultUI: true },
  internal: { id: 'map' }
}, function(){
  var pins = mapHandler.addMarkers(<%=raw @map_data.to_json %>);
  mapHandler.bounds.extendWith(pins);
  mapHandler.fitMapToBounds();
});
</script>

In the posts/summary partial:

$('#post_<%= post.id %>').click(function() {
  var newCenter = new google.maps.LatLng(<%= post.lat %>, <%= post.lng %>);
  var newMap = new google.maps.Map(document.getElementById('map'));
  newMap.setZoom(13);
  newMap.setCenter(newCenter);
  newMap.setMapTypeId(google.maps.MapTypeId.ROADMAP);
});

How can I use the mapHandler from the index in my partial to just recenter the existing map?

hey luke, i think ur prob is u’re creating a new map instance in the partial. instead, try accessing the existing mapHandler like this:

$('#post_<%= post.id %>').click(function() {
  var newCenter = new google.maps.LatLng(<%= post.lat %>, <%= post.lng %>);
  mapHandler.getMap().setCenter(newCenter);
  mapHandler.getMap().setZoom(13);
});

this shud center the existing map without reloading. lmk if it works!

I’ve encountered a similar issue before. The key is to make the mapHandler globally accessible. Try modifying your index.html.erb script like this:

window.mapHandler = Gmaps.build('Google');
window.mapHandler.buildMap({
  // ... rest of your existing code
});

Then in your partial, you can directly use the global mapHandler:

$('#post_<%= post.id %>').click(function() {
  var newCenter = new google.maps.LatLng(<%= post.lat %>, <%= post.lng %>);
  window.mapHandler.getMap().setCenter(newCenter);
  window.mapHandler.getMap().setZoom(13);
});

This approach should allow you to manipulate the existing map without reloading. It’s more efficient and provides a smoother user experience.

I’ve dealt with this exact problem in a project I worked on. The solution that worked for me was to use a custom event system. Here’s what I did:

In your index.html.erb, after initializing the map, add an event listener:

$(document).on('centerMap', function(e, lat, lng) {
  var newCenter = new google.maps.LatLng(lat, lng);
  mapHandler.getMap().setCenter(newCenter);
  mapHandler.getMap().setZoom(13);
});

Then in your partial, trigger the event instead of trying to manipulate the map directly:

$('#post_<%= post.id %>').click(function() {
  $(document).trigger('centerMap', [<%= post.lat %>, <%= post.lng %>]);
});

This approach keeps your map logic centralized and avoids scope issues. It’s also more flexible if you need to add more map interactions later.