Retain data editor changes while switching pages

Hi,
I’ve seen numerous posts on this topic, but most of the solutions don’t seem to work. I’ve found a way to make changes persist across pages for the data editor. While there may be a better solution out there, this approach actually works.

Problem
When the same key is used for both initializing and saving changes (as in the following setup), the data keeps disappearing. Users are forced to enter each change twice before the session state is updated.

st.session_state['df'] = st.data_editor(st.session_state['df'])

Additionally, data is deleted when switching between pages. This happens because the widgets are cleared from the session state during page transitions.

Solution
All edits are stored in a dictionary under their respective categories (edit, add, delete). By applying these changes to the dataframe stored in the session state within the ‘on change’ callback, we can update the session state before the page reloads.

Code example
First initialize the private key.

if 'df' not in st.session_state:
    st.session_state['df'] = DEFAULT_DF
def store_df(key):
    pkey = '_' + key
    changes = st.session_state[pkey]
    df = st.session_state[key]

    # Apply edits
    for row, edit in changes['edited_rows'].items():
        for column, new_value in edit.items():
            df.loc[row, column] = new_value

    # Apply added rows
    for row in changes['added_rows']:
        # Create empty row
        df.loc[df.shape[0]] = None
        df = df.reset_index(drop=True)

    # Remove deleted rows
    df = df.drop(changes['deleted_rows'])

    # Store the dataframe in the session key
    st.session_state[key] = df

Now call the editor using:

data = st.session_state['df']
edited_data = st.data_editor(data, num_rows='dynamic', key='_df', on_change=store_df, args=['df'], hide_index=True)

Alternatives considered
Some alternatives that work for selection boxes and other widgets often don’t work for the data editor. For example:

def on_change(key):
    st.session_state[key] = st.session_state['_'+key]

Does not work properly as it appears to be called before the private session state variable is updated.

1 Like

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