Multipage with multiselect default and session state

Summary

I have a multi-select drop down with default value on the side bar. I am trying to persist the selected value and show the selected value in the drop down after I switch to another page and switch back.

Folder structure:

Screen Shot 2023-10-02 at 3.52.15 PM

Current issue

however, the drop down disappeared after I select another value โ€œSFโ€ (which makes sense because now session_state has a value so it doesnโ€™t run the function to show the multi-select drop down). What I am confused about is that, if I want the multi-select drop down to show at all time, I would need to run selected_values in my load_functions.py at all timeโ€ฆ but then upon changes, I would need to replace the current hard coded default value NYC with the session_state value that stored the user selected input. I think I may need to use some action like on_change and I am struggling with that. Also, does it make sense to have the code for the first and second page side bar to be exactly the same? I simply just want a side bar with selected drop down value to be persistent during the session and shown on the side bar

1-apple.py

import streamlit as st
from load_functions import selected_values, load_df

if 'df' not in st.session_state:
    df =  load_df() 
    st.session_state['df'] = df
else:
    df = st.session_state['df']

with st.sidebar:
    if 'cities' not in st.session_state:
        selected_cities = selected_values(df)
        st.session_state['cities'] = selected_cities
    else:
        selected_cities = st.session_state['cities']

st.write(f"Session state:  {st.session_state['cities']}")

2-banana.py

import streamlit as st
from load_functions import selected_values, load_df

if 'df' not in st.session_state:
    df =  load_df() 
    st.session_state['df'] = df
else:
    df = st.session_state['df']

with st.sidebar:
    if 'cities' not in st.session_state:
        selected_cities = selected_values(df)
        st.session_state['cities'] = selected_cities
    else:
        selected_cities = st.session_state['cities']

st.write(f"Session state:  {st.session_state['cities']}")

load_functions.py

import streamlit as st
import numpy as np
import pandas as pd

def selected_values(df):

    cities = np.sort(df['city'].unique())
    city_container = st.container()
    all_cities = st.checkbox("Select all", key=1)

    if all_cities:
        selected_cities = city_container.multiselect("Select one or more city:",
                                                        cities, 
                                                        cities)
    else:
        selected_cities =  city_container.multiselect("Select one or more city", 
                                                        cities, 
                                                        default=['NYC'])

    return selected_cities


def load_df():
    # initialize data of lists.
    data = {'city': ['NYC', 'NYC', 'SF', 'Plano', 'SLC', 'SF'],
            'age': [20, 21, 19, 18, 21, 22]}
    # Create DataFrame
    df = pd.DataFrame(data)
    return df

FROM:

TO: (When I select SF)

Expected result:

When I select SF, I want the drop down selection to show only SF and when I switch to page banana, I want SF to show, when I switch back to page apple, I want SF to show.

More:

I also tried to modified some code in load_functions.py but it still doesnโ€™t work as expected. Also tried

st.session_state.my_widget_key = st.session_state.my_widget_key

Please let me know if clarification is needed and please help. Thank you!

Use this as reference.

Is there anyone here?

Here is an update.

I used the suggested best way to do it. It works well when dealing with 1 multi-select on the side bar. However, when I do it for 2 multi-select and clear out one of the multi-select boxes to re-select, both of the multi-select disappeared and I got an error. Any idea why?

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Current code:

def save_value(key):
    st.session_state[key] = st.session_state["_"+key]

def get_value(key):
    st.session_state["_"+key] = st.session_state[key]



def selected_values(df):

    cities = np.sort(df['city'].unique())
    ptypes = np.sort(df['ptype'].unique())

    if "multi_select_cities" not in st.session_state:
        st.session_state["multi_select_cities"] = cities

    city_container = st.container()
    get_value("multi_select_cities")
    selected_cities = city_container.multiselect("Select one or more city:",
                                                cities, 
                                                key="_multi_select_cities",
                                                on_change=save_value,
                                                args=['multi_select_cities'])

    
    if "multi_select_ptypes" not in st.session_state:
        st.session_state["multi_select_ptypes"] = ptypes

    ptype_container = st.container()
    get_value("multi_select_ptypes")
    selected_ptypes = ptype_container.multiselect("Select one or more pytpes:",
                                                ptypes, 
                                                key="_multi_select_ptypes",
                                                on_change=save_value,
                                                args=['multi_select_ptypes'])


    # all_ptypes = st.checkbox("Select all", key=2)
    # if all_ptypes:
    #     selected_ptypes = ptype_container.multiselect("Select one or more property type:", ptypes, ptypes)
    # else:
    #     selected_ptypes =  ptype_container.multiselect("Select one or more property type:", ptypes, default=['SF'])


    return selected_cities, selected_ptypes
1 Like

Solved this by changing these 2 lines to hardcoded default value. This is where you set your default!!

    if "multi_select_cities" not in st.session_state:
        st.session_state["multi_select_cities"] = ["NYC"]
    if "multi_select_ptypes" not in st.session_state:
        st.session_state["multi_select_ptypes"] = ["SF"]
1 Like

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