I'd like to update a text input in a pyshiny app each time a marker is clicked in an ipyleaflet map widget using the marker's title value. I have been using the marker.on_click() callback to get the title (station_id in this case) from the clicked marker, but I am struggling to dynamically change the text input box with the title text.
A basic working example that I have tried is shown below. The title of each marker is printed to screen from within the callback() function each time it is clicked. However, I can't figure out how to update the ui.input_text's value. The Reactive.Effect function does not seem to be called at all and I'm not sure why. What do I need to change here to update the value in the text input?
from shiny import App, reactive, run_app, ui
from shinywidgets import output_widget, register_widget
import ipyleaflet as ipyl
app_ui = ui.page_fluid(
{"class": "p-4"},
ui.row(
ui.column(
4,
ui.input_text("station_id", "Station ID:", value="Click on a station marker"),
),
ui.column(
8,
output_widget("map_widget")
),
),
)
def get_station_id(_marker):
def callback(*args, **kwargs):
print(_marker.title)
return _marker.title
return callback
def add_stations_to_map(_map, stations):
markers = []
for station in stations:
marker = ipyl.Marker(location=station[0], draggable=False, title=station[1])
_map.add(marker)
markers.append(marker)
return markers
def server(input, output, session):
# Initialize and display when the session starts (1)
_map = ipyl.Map(center=(-33.8, 151), zoom=8, scroll_wheel_zoom=True)
# Add a distance scale
_map.add(ipyl.leaflet.ScaleControl(position="bottomleft"))
register_widget("map_widget", _map)
# add markers and station id clik function
stations = [
[(-33.8, 151), "station_1"],
[(-33.8, 150), "station_2"],
]
markers = add_stations_to_map(_map, stations)
clicked_marker = "Click on a station marker"
for marker in markers:
clicked_marker = marker.on_click(get_station_id(marker))
@reactive.Effect
def _():
ui.update_text("station_id", value=clicked_marker)
app = App(app_ui, server, debug=True)
run_app(app, launch_browser=True, port=0)
You can use a reactive.Value to set your text:
clicked_marker_value = reactive.Value("Click on a station marker")
def get_station_id(_marker):
def callback(*args, **kwargs):
print(_marker.title)
clicked_marker_value.set(_marker.title)
return _marker.title
return callback
@reactive.Effect
def _():
ui.update_text("station_id", value=clicked_marker_value())