Sharing multiselect between different pages

Use case

I would like to create a multi-page app and have some multiselect fields that would be shared between those pages. e.g. if the multiselect is updated in one page, it should be remembered when I move to another page

The approach I followed is to:

  1. store the results of my multiselect project_names in st.session_state
  2. set the default value of my multiselect to use the st.session_state.get("project_names")

Problem

Overall, it sort of works, but I have an issue when selecting/deselecting multiple values

  • the first time I select a value, everything is OK
  • but when I want to select another value, the first time I select it, the page refreshes, without taking in account the new selection. And if I select it again, this time, my multiselect gets updated
  • this behaviour then repeats for every new value I want to select
    • the first time, it doesn’t work
    • it works the second time

Current code

I used this code in a shared file to define my multiselect

def filter_projects_env(df, project_column_name):

    project_names = st.sidebar.multiselect(
        label="Project Name", options=df[project_column_name].unique(), default=st.session_state.get("project_names")
    )
    st.session_state["project_names"] = project_names

    if project_names:
        df = df[df["project_name"].isin(project_names)]
    return df

And then, just call it in my different pages like this:

# pages/page1.py
...
df_projects = filter_projects_env(df_projects, "project_name")
...
# pages/page2.py
...
df_jobs = filter_projects_env(df_jobs, "project_name")
...

Is it a known behaviour and/or is there a way to achieve what I am trying to do?

Python 3.9.12
Streamlit, version 1.28.2

Hi @b-per

Typically if widgets needs to be clicked twice to work, it most likely can be fixed by embedding your session state variables as callback functions.

Here’s a pseudo-code:

def your_callback_function():
   st.session_state.count = '123'

st.button('Click me', on_click=your_callback_function)

Hope this helps!

Thanks a lot for pointing me on the callback direction!

I updated the project_names with

    project_names = st.sidebar.multiselect(
        label="Project Name", options=df[project_column_name].unique(), default=st.session_state.get("project_names"), key='filter_projects', on_change=update_projects
    )

and created the callback function

def update_projects():
   st.session_state["project_names"] = st.session_state.filter_projects

and it seems to be working as expected now!

1 Like

@b-per Glad to hear that it is working now, happy Streamlit-ing!

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