Filter data in data_editor

It’s not particularly dependent on other stuff. Basically move the commit callback function to the filter input and then ensure the commit action is at the top of every other page to make sure edits are not lost if someone filters+edits+changes pages (without unfiltering) or makes an edit while not filtered (and doesn’t immediately change the filter). You could also add a confirm button or something to make sure any final edits are committed; it just depends on what kind of a workflow you want the users to have.

import streamlit as st
import pandas as pd
import time

if "dfa" not in st.session_state:
    st.session_state["dfa"] = pd.DataFrame(
        {
            "Par": ["Apple", "Strawberry", "Banana"],
            "Cat1": ["good", "good", "bad"],
            "Cat2": ["healthy", "healthy", "unhealthy"],
            "Active": [False, False, False],
        }
    )


def active_dfa():
    return st.session_state["dfa"][st.session_state["dfa"]["Active"] == True].copy()


def get_index(row):
    return active_dfa().iloc[row].name


def commit():
    for row in st.session_state.editor["edited_rows"]:
        row_index = get_index(row)
        for key, value in st.session_state.editor["edited_rows"][row].items():
            st.session_state["dfa"].at[row_index, key] = value


st.header("Filter and edit data")
name = st.text_input("Search for ...", on_change=commit)
if name == "":
    st.session_state["dfa"].Active = True
else:
    st.session_state["dfa"].Active = False
    st.session_state["dfa"].loc[
        st.session_state["dfa"]["Par"].str.contains(name, case=False), "Active"
    ] = True

edited_dfa = st.data_editor(
    active_dfa(), column_order=["Par", "Cat1", "Cat2"], key="editor"
)

st.button("Save", on_click=commit)

At the beginning of every other page (if you have them), after importing or redefining the necessary functions, add:

if "dfa" in st.session_state:
    commit()
1 Like