Hello Streamlit community,
I’m facing a challenging issue with my Streamlit app that involves a data_editor and action buttons. My goal is to prevent users from clicking action buttons while they’re in the middle of editing data to avoid losing their changes.
The Problem
-
When a user is actively editing a cell in the data_editor and clicks a button:
- The app first reruns with the button’s logic
- Only then does it rerun to update the data_editor value
- This can lead to data loss or unexpected behavior
-
I’ve tried implementing CSS to disable buttons while editing:
body:has([data-testid=“stDataFrame”] *:focus) .stButton {
pointer-events: none;
opacity: 0.3;
cursor: not-allowed;
} -
This works well until the user changes browser tabs or loses focus on the page - when they return, the CSS effect is canceled even if they were in the middle of editing.
Is there a reliable way to:
- Force the data_editor to save changes before any button action processes?
- OR maintain the disabled state of buttons even when the page loses focus?
- OR detect when a cell is being edited, even after tab change?
Any help would be greatly appreciated!
Here is a code sample for a CSS solution (not working if the user switches to another tab/application and return, the CSS protection is lost) :
import streamlit as st
import pandas as pd
data = pd.DataFrame({
‘Nom’: [‘Jean’, ‘Marie’, ‘Pierre’, ‘Sophie’],
‘Âge’: [28, 34, 42, 25],
‘Ville’: [‘Paris’, ‘Lyon’, ‘Marseille’, ‘Bordeaux’]
})
st.markdown(“”"
[data-testid="stDataFrame"]:has(*:focus), [data-testid="stDataFrame"]:has(*:focus-within), [data-testid="stDataFrame"]:has([role="gridcell"][aria-selected="true"]), [data-testid="stDataFrame"]:has(input:focus) { box-shadow: 0 5px 20px rgba(0, 0, 255, 0.4); border: 3px solid blue !important; z-index: 1000; position: relative; } /* Unable to click on buttons when the table is in focus */ body:has([data-testid="stDataFrame"] *:focus) .stButton, body:has([data-testid="stDataFrame"] *:focus-within) .stButton, body:has([data-testid="stDataFrame"] [role="gridcell"][aria-selected="true"]) .stButton, body:has([data-testid="stDataFrame"] input:focus) .stButton { pointer-events: none; opacity: 0.3; cursor: not-allowed; filter: grayscale(100%); }“”", unsafe_allow_html=True)
edited_df = st.data_editor(
data,
key=“unique_editor”
)
if st.button(“Test”, key=“test_button”):
st.balloons()