Update Folium map with st.button

Hey everyone, i am building a small python webapp to edit csv files before commiting for further processing. The CSV data contains point observations described by a decimal_longitude and decimal_latitude collumn. They get plotted on a map and by clicking on a point and pressing the remove button, they should be dropped from the csv file and the map should automatically update.

Now the problem: When the button is pressed, the selected point is dropped, but the map doesnt update. only when i press the button again, the map updates.
Hpw can this be fixed? The code is mentioned bellow:

import folium
import streamlit as st
from streamlit_folium import st_folium
import pandas as pd
import folium.plugins as plugins

def mapcsv():
    obs=pd.DataFrame()

    obs_file = st.file_uploader("Choose a file")
    if obs_file is not None:
        # To read file as bytes:
        bytes_data = obs_file.getvalue()
        # Can be used wherever a "file-like" object is accepted:
        obs = pd.read_csv(obs_file, sep='\t')


        if "obs" not in st.session_state:
            st.session_state.obs= obs
        if "obs_edit" not in st.session_state:
            st.session_state.obs_edit= obs
        obs_edit=st.session_state.obs_edit
        if "center" not in st.session_state:
            st.session_state["center"] = [ 19.8,-96.85]  # Default center for the map
        if "out" not in st.session_state:
            st.session_state.out={}
        
        if "zoom" not in st.session_state:
            st.session_state["zoom"] = 8  # Default zoom level

        lat_col = "decimal_latitude"
        lon_col = "decimal_longitude"
        obs_edit=st.session_state.obs_edit

        def render_map():
            fg = folium.FeatureGroup(name="Markers")
            m = folium.Map(
                location=st.session_state["center"], 
                zoom_start=st.session_state["zoom"]
            )
            for i, row in obs_edit.iterrows():
                fg.add_child(folium.Marker(
                    location=[row[lat_col], row[lon_col]],
                    tooltip="Click to select",
                    icon=plugins.BeautifyIcon(icon="circle")
                ))
            st.session_state.out = st_folium(
                m,
                center=st.session_state["center"],
                zoom=st.session_state["zoom"],
                key="out",
                feature_group_to_add=fg,
                height=400,
                width=700,
            )
        render_map()

        index=obs_edit.index[(obs_edit[lat_col] == st.session_state.out["last_object_clicked"]["lat"]) & 
                                  (obs_edit[lon_col] == st.session_state.out["last_object_clicked"]["lng"])]


        if st.button("remove point"):
            st.session_state.obs_edit=obs_edit.drop(index)

Hi @Simon5, welcome to the forum!

One minor suggestion for your post – could you edit it so that the whole code sample is a codeblock? You can do that by putting ``` before and after your code.

I think the easy fix to the issue you’re having is to use a callback on the button – the big difference in this is that callbacks run as if they’re at the top of the app code, so it will update the session state and THEN render the map with the updated values.

def remove_point(index):
    st.session_state.obs_edit=obs_edit.drop(index)

st.button("remove_point", on_click=remove_point, args=(index,))

Hey @blackary, thanks for suggestion, will do. The fix worked, thanks alot!

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.