Hi everyone,
I’m encountering a frustrating issue with the st.data_editor
component in my Streamlit application. I use this component to allow users to interactively modify a table. However, I’m experiencing intermittent problems where, when switching between columns and entering new values, a rerun callback is triggered. This rerun causes me to lose all the changes and values I’ve just entered.
While some values are saved in session_state
, it’s not consistent, and this behavior disrupts the user experience. Ideally, once the application is initialized and the user interacts with the table, all values should be reliably saved in session_state
. As it stands, users find themselves repeatedly re-entering values until the table is finally in a state where it can be saved to the database.
Has anyone encountered a similar issue or have suggestions for ensuring that all values are consistently saved? Any help would be greatly appreciated!
Thanks in advance!
Demo Code:
# Placeholder dictionary (you should replace this with your actual dictionary)
dct = {
"supplier": "Supplier",
"invoice_number": "Invoice Number",
"invoice_date": "Invoice Date",
"due_date": "Due Date",
"net_amount": "Net Amount",
"gross_amount": "Gross Amount",
"payment_status": "Payment Status",
"due_status": "Due Status",
"note": "Note",
"dropdown_options": {"Option1": "Option 1", "Option2": "Option 2"},
"not_due": "Not Due",
"due": "Due"
}
def load_or_initialize_session_data(page_data_key, page_key):
"""Load or initialize session state data for the given page."""
if page_data_key not in st.session_state:
st.session_state[page_data_key] = db.load_user_data()
if page_key not in st.session_state:
st.session_state[page_key] = 0
return st.session_state[page_data_key]
def app(page="demo"):
# Assign the specific formats to column types
column_config = {
dct.get("supplier"): st.column_config.TextColumn(),
dct.get("invoice_number"): st.column_config.TextColumn(),
dct.get("invoice_date"): st.column_config.DateColumn(format="dd/MM/yyyy"),
dct.get("due_date"): st.column_config.DateColumn(format="dd/MM/yyyy"),
dct.get("net_amount"): st.column_config.NumberColumn(format="%.2f €", default=0.0),
dct.get("gross_amount"): st.column_config.NumberColumn(format="%.2f €", default=0.0),
dct.get("payment_status"): st.column_config.SelectboxColumn(
options=list(dct.get("dropdown_options").values()), required=True
),
dct.get("due_status"): st.column_config.SelectboxColumn(
options=[dct.get("not_due"), dct.get("due")],
required=True,
default=dct.get("not_due"),
),
dct.get("note"): st.column_config.TextColumn(),
}
# Compose a list of all relevant columns
all_columns = list(column_config.keys())
# Determine the effective identifier for the page or table
effective_identifier = page
# Construct the page data key and page key
page_data_key = f"{effective_identifier}_data"
page_key = f"{effective_identifier}_key"
# Load or initialize session state data
data = load_or_initialize_session_data(
page_data_key=page_data_key, page_key=page_key
)
# Construct the respective page editor key
page_editor_key = f"{effective_identifier}_editor_{st.session_state[page_key]}"
# Display editable data table
edited_data = st.data_editor(
data,
key=page_editor_key,
num_rows="dynamic",
column_config=column_config,
use_container_width=True,
hide_index=False,
)
# Convert edited data to DataFrame and calculate available money
df = pd.DataFrame(edited_data).reset_index(drop=True)
Debugging info:
- The app is running locally
- Streamlit version: 1.38.0
- Python version: 3.11.9