-
Notifications
You must be signed in to change notification settings - Fork 361
Description
Hello,
I am fairly new to using ipyleaflet and am trying to create a test app using Shiny Express that 'selects' a marker and highlights it on a map. I have a Shiny input_select with a list of locations and the locations are displayed as markers on the map in a LayerGroup. When I select a city in the dropdown I have a reactive effect that should replace the marker for the selected location with a new one with a different icon (note: I've tried just changing the icon on the existing marker, but that doesn't correctly update on the map). I'm doing this using the .add and .remove methods on the LayerGroup. I've also tried just adding the markers to the map directly instead of using a LayerGroup and get the same result.
I'm getting some odd behavior where the marker for the currently selected location just disappears from the map and then re-appears after selecting a different city. I think I've tracked this down to what appears to be a bug in the logic that gets triggered by the .add method. Looking in the developer console in Firefox, I noticed that there is an error that triggers: 'Uncaught (in promise) TypeError: can't access property "state_change", t is undefined'. The behavior is the same in Edge.
I'm not sure if this is actually a problem with ipyleaflet or if it's something with shinywidgets or ipywidgets and unfortunately don't know where to begin to track down the issue. Does anyone know what I might be able to do as a workaround?
Version info:
Windows 11
Python 3.12
ipyleaflet 0.20.0
shinywidgets 0.7.0
ipywidgets 8.1.7
Example:
from shiny import reactive
from shiny.express import ui, input
from ipyleaflet import Map, Marker, LayerGroup, AwesomeIcon
from shinywidgets import render_widget
capital_cities = [
{"city": "Dublin", "lat": 53.35, "lon": -6.26, "population": 1.30},
{"city": "London", "lat": 51.51, "lon": -0.13, "population": 9.84},
{"city": "Edinburgh", "lat": 55.95, "lon": -3.19, "population": 0.56},
{"city": "Belfast", "lat": 54.60, "lon": -5.93, "population": 0.35},
{"city": "Cardiff", "lat": 51.48, "lon": -3.17, "population": 0.50},
]
ui.page_opts(title="Map")
_cities = [x["city"] for x in capital_cities]
_cities.sort()
ui.input_select(
"selected_city",
"Select a city:",
_cities,
)
@render_widget
def display_map():
map_ = Map(center=(51, 0), zoom=5)
map_.layout.height = '600px'
# Create markers first
markers = []
for city in capital_cities:
m = Marker(location=(city["lat"], city["lon"]), name=city["city"], title=city["city"])
m.icon = AwesomeIcon(name="hand-spock-o", marker_color="red")
markers.append(m)
# Put the markers in a layergroup and plot
group = LayerGroup(layers=markers)
map_.add(group)
return map_
@reactive.effect
def change_selected_city_marker():
city = input.selected_city.get()
print(city)
marker_group = display_map.widget.layers[1] # I have confirmed that this is the correct LayerGroup
markers = marker_group.layers
print("Number of markers before update:", len(markers))
for m in markers:
if m.name == city:
print(f"Old Marker:\n{m}")
updated_marker = Marker(
location=m.location,
name=m.name,
title=m.title,
icon=AwesomeIcon(name="hand-spock-o", marker_color="green")
)
print(f"New Marker:\n{updated_marker}")
marker_group.remove(m)
marker_group.add(updated_marker)
break
print("Number of markers after update:", len(marker_group.layers))