Preserve row selection on page reload & restore in multipage app?

Hi,

I am trying the multipage method. On the first page I have an ag-grid component. On selecting a row I display further information. If I navigate to another page (actually there is a button and code which will transfer selected data to another page) and come back, the first page has been rerun and the table is back to an unselected state.

I’d like to capture the selected row and restore it - using either st.session_state or my own state machine.

Thank you so much.

2 Likes

@dave51c were you able to find a solution for this ?

I have the exact challenge.

jodi319

Here’s one solution:

import pandas as pd
import streamlit as st
from st_aggrid import AgGrid, GridOptionsBuilder

for k, v in st.session_state.items():
    st.session_state[k] = v

df = pd.DataFrame(
    {
        "index": [0, 1, 2],
        "col1": [1, 2, 3],
        "col2": [2, 3, 4],
    }
).set_index("index")


gb = GridOptionsBuilder.from_dataframe(df)

try:
    selected_row = st.session_state["table_key"]["selectedItems"][0]["rowIndex"]
except (KeyError, IndexError):
    selected_row = 0

gb.configure_selection("single", pre_selected_rows=[selected_row])
grid_return = AgGrid(
    df, gridOptions=gb.build(), fit_columns_on_grid_load=True, key="table_key"
)

And also put the following at the top of each page in the app (this fixes an issue where the automatic session state entry associated with the table’s key doesn’t get removed when you switch pages)

for k, v in st.session_state.items():
    st.session_state[k] = v

this is not working…

above code is not working. Could you help us?

Hi @Manoharan_Thambi, could you share a reproducible code snippet showing what you’ve tried to do and what’s not working about it?

In general, the solution to keeping widget state around is to make sure this line is at the top of all of your pages in your app.

for k, v in st.session_state.items():
    st.session_state[k] = v
1 Like

@blackary
thanks for the response!
Below code works for me as expected.

import pandas as pd
import streamlit as st
from st_aggrid import GridOptionsBuilder, AgGrid, GridUpdateMode, DataReturnMode, ColumnsAutoSizeMode

if "selected_row" not in st.session_state:
    st.session_state.selected_row = '0'

data = {
    "calories": [420, 380, 390, 410, 420, 550, 600],
    "duration": [50, 40, 45, 50, 55, 60, 65],
    "random1": [5, 12, 1, 4, 5, 6, 7]
}

df = pd.DataFrame(data)

gb = GridOptionsBuilder.from_dataframe(df)
if "id_row" not in st.session_state:
    st.session_state["id_row"] = ''
    st.session_state.selected_row = '0'
else:
    st.session_state.selected_row = st.session_state["id_row"].get('selectedItems')[0]['_selectedRowNodeInfo'][
        'nodeRowIndex']

st.write(st.session_state.selected_row)

gb.configure_selection(selection_mode="single",
                       pre_selected_rows=[str(st.session_state.selected_row)])
gridOptions = gb.build()

data = AgGrid(df,
              gridOptions=gridOptions,
              enable_enterprise_modules=True,
              allow_unsafe_jscode=True,
              update_mode=GridUpdateMode.MODEL_CHANGED, key='id_row')

selected_rows = data["selected_rows"]
if len(selected_rows) != 0:
    st.write(selected_rows[0])
    # st.session_state.selected_row = selected_rows[0]['_selectedRowNodeInfo']['nodeRowIndex']

1 Like

Unfortunately, the suggested solution does not work if the dataframe contains random values. I have opened a new thread to discuss this issue, which you can find here:

Hi,

Hope the below code snippet helps

        df = pd.DataFrame({
            'name': ['Thailand', 'Taiwan', 'Kenya' ],
            'city': ['Bangkok', 'Taipei', 'Nairobi']
        })

        sel = []
        if os.path.isfile('saved.csv'):
            sel = pd.read_csv('saved.csv')['name'].tolist()

        cellstyle_jscode = JsCode(f"""
            function(params){{
                var valuesToCheck = {sel};
                if (valuesToCheck.includes(params.value)) {{
                    params.node.setSelected(true);
                }}
            }};
        """)

        gb = GridOptionsBuilder.from_dataframe(df)
        gb.configure_selection(selection_mode="multiple", use_checkbox=True)
        gb.configure_columns(['name'], cellStyle=cellstyle_jscode)
        
        gridOptions = gb.build()

        grid_data = AgGrid(df, key='sample', gridOptions=gridOptions, 
               update_mode = GridUpdateMode.SELECTION_CHANGED,
               allow_unsafe_jscode=True,
               reload_data=True,
               enable_enterprise_modules=True
                )

        if st.button('Save selected rows'):
            try:
                selected_rows = grid_data['selected_rows'] 
                df1 = pd.DataFrame(selected_rows).drop('_selectedRowNodeInfo', axis=1)
                df1.to_csv('saved.csv')
            except Exception as e:
                st.write('Select at least one row to save')