Google Map: multiple InfoWindow event handlers

The maps docs page includes this example:

def marker_click(sender, **event_args):
  i =GoogleMap.InfoWindow(content=Label(text="This is Cambridge!"))
  i.open(map, sender)

marker.set_event_handler("click", marker_click)

which works!

However, I’m trying to run this code in a loop (create a marker for every location in the database, and add a label to show the location name for each one). The code I’m using:

def __init__(self, **properties):
    self.init_components(**properties)
    events = anvil.server.call('get_events')
    
    for event in events:
      position = GoogleMap.LatLng(event['latitude'], event['longitude'])
      marker = GoogleMap.Marker(position=position)
      self.map.add_component(marker)
      
      def marker_click(sender, **event_args):
        i = GoogleMap.InfoWindow(content=Label(text=event['event_name']))
        i.open(self.map, sender)

      marker.set_event_handler("click", marker_click)

Which makes all the text labels the same, because presumably the marker_click function is being garbage collected.

I have a feeling I’ve solved this problem before, but I don’t have access to the code where I last tried it!

Not specific to any issue you have, but …

do you need to create one handler per event in a loop?

Surely you can just create that handler just once and set all events to use the same routine, passing any specific info from the event itself as a parameter?

That might not be your problem, but that does look a little strange to me.

Thanks, I solved it by doing that.

def __init__(self, **properties):
  self.init_components(**properties)
  self.markers = {}
  
  events = anvil.server.call('get_events')
  
  for event in events:
    position = GoogleMap.LatLng(event['latitude'], event['longitude'])
    marker = GoogleMap.Marker(position=position)
    self.map.add_component(marker)
    self.markers[marker] = event['event_name']
    marker.set_event_handler("click", self.marker_click)
    
def marker_click(self, sender, **event_args):
  event_name = self.markers[sender]
  i = GoogleMap.InfoWindow(content=Label(text=event_name))
  i.open(self.map, sender)
1 Like

Yes! What happened in your first version was that the marker_click function was accessing the event variable from the __init__ function – but by the time that marker_click ran, that variable had changed!

You found one way to do it. Another way to do it is to set the tag property on the component (or, in this case, marker), then use sender.tag in the event handler to access that data.

Thanks! Very helpful solution.
The following example is the solution using tag.

def marker_click(sender, **event_args):
  i =GoogleMap.InfoWindow(content=Label(text=sender.tag))
  i.open(map, sender)

marker = GoogleMap.Marker(position=position)
marker.tag = 'the text you want to show'
marker.add_event_handler("click", marker_click)