Save file_uploader and text_input state or cache when changing select_box option

Hello, I have a page on which I use a select_box, which I want to redirect me towards different algorithms. For each select_box, I create two file_uploader and a text_input, whose output is then used by a function. When I upload a file in one of the file_uploader, change the select_box option, and come the file_uploader is empty, and so is the text_input
I would like my file_uploader and my txt_input to keep in โ€œmemoryโ€ (maybe by caching or by using the session_state) the last uploaded file and text input, so that it is still here when I switch select_box option. Is that possible ?

What Iโ€™m doing right now is this:

import streamlit as st

def display_labels(label):
    if label == 1:
        return "Image to Point Cloud"
    elif label == 2:
        return "Text to Point Cloud"
    elif label == 3:
        return "Point Cloud to Mesh"

point_e_algo = st.selectbox("Choose which algorithm you want to use:",
                            range(1, 4),
                            format_func=display_labels)

if point_e_algo == 1:
    help = "Upload the image you want to turn into a 3D Point Cloud."
    img = st.file_uploader(help, type=["png", "jpg", "jpeg"])
    if img is not None:
        process_img(img) # customized function that I cached with st.cache
elif point_e_algo == 2:
    help = "Please enter the prompt you want to turn in a 3D Point Cloud."
    prompt = st.text_input(help)
    if prompt is not None:
        process_txt(prompt) # customized function that I cached with st.cache
elif point_e_algo == 3:
    help = "Upload a Point Cloud file to turn it into a mesh."
    npz = st.file_uploader(help, type=["npz"])
    if npz is not None:
        process_npz(npz) # customized function that I cached with st.cache

And is there a way to let the processing functions run in the background when I switch the select_box options ?

Thanks in advance for your help

Information for a widgetโ€™s state is discarded whenever a widget is not rendered (either conditionally or from switching pages). For most widgets (including text_input) you can copy the widget state into a different key and copy it back when the widget reappears:

import streamlit as st

# Initialize and set default value
if '_my_key' not in st.session_state:
    st.session_state._my_key='Default value for the widget'
# Copy from placeholder to widget key
st.session_state.my_key = st.session_state._my_key

def keeper(key):
    # Copy from widget key to placeholder
    st.session_state['_'+key] = st.session_state[key]

st.text_input('Label', key='my_key', on_change=keeper, args=['my_key'])

However, file_uploader doesnโ€™t allow you to assign state like other widgets, so there is a difficulty there. Whenever you change any of the creation parameters of a widget, a new widget will be created.

Possible options:

  1. Render all three at all times and use tabs to switch between them. (You would still lose info if leaving the page and returning.)
  2. Copy the information into another key in session state. The example for text_input is given above, but for file_uploader you would just be storing the files and listing out separately that they are in memory, giving the user the option to use the last submitted or to submit a different batch. (If needed you could make this more robust with options to delete from or add to the existing list from the last render.)
1 Like

Worked like a charm. Thanks a lot for your help @mathcatsand !

1 Like

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