Multiselect Not Retaining User Selection

I am trying to get user input corresponding to 3 cases (given in st.session_state.steps) and save them in options.pkl. I trying to do this using st.form and st.multiselect. However, what gets saved does not correspond to what I select. For example, if I selected ‘Option B’ for ‘step 1’, ‘Option A’ for ‘step 2’, and ‘Option C’ for ‘step 3’, what gets saved are ,

[{'step 1': ['Option A']}, {'step2': ['Option B']}, {'step3': ['Option C']}] .

That is, ‘Option A’ for ‘step 1’, ‘Option B’ for ‘step 2’, and ‘Option C’ for ‘step 3’.

So, it looks like the default option (Option A) gets appended to the list even before I make selections for the first time. Is there a way fix this?

If there are any other ways to get this done (without using st.form/multiselect), that would be helpful too.

Code to reproduce the above issue:

import streamlit as st
import pickle


tags_values = ['Option A','Option B', 'Option C']

if 'steps' not in st.session_state:
    st.session_state.steps = ['step 1', 'step2', 'step3']   

if 'iteration_count' not in st.session_state:
    st.session_state.iteration_count = 0   

if 'tag_options' not in st.session_state:
    st.session_state.tag_options = []

def save_options(options):
    st.session_state.tag_options.append(options)

selected_tags = ['Option A']

if st.session_state.iteration_count <  3:

    i = st.session_state.iteration_count
    step_text = st.session_state.steps[i] 
    message = f"what are the options for {step_text}?"

    tags = st.markdown(message)

    with st.chat_message('system'):
            
        with st.form(key='tags'):

            options = st.multiselect(
                    '',
                    tags_values,
                    selected_tags,
                        )
            submit_button_tags = st.form_submit_button(label='submit_tags', on_click=save_options, args = [{step_text:options}])


    st.session_state.iteration_count +=1

with open('options.pkl', 'wb') as f:
    pickle.dump(st.session_state.tag_options, f)

When you use arguments in a callback, the arguments are loaded when the widget is rendered. So when the form is rendered, the submit button’s callback is using the multiselect’s default value. When the user changes the multiselect, the output of the widget does not change because it’s in a form. Then, when the submit button is clicked, the callback executes (still using the default value) and when the app reruns, only then would the output be updated.

To use a form’s data in a callback, assign keys to the form widgets and then retrieve the widget values from Session State within the callback.

1 Like

Thank you very much!

Below is the solution code I came up with based on your suggestion.

import streamlit as st
import pickle


tags_values = ['Option A','Option B', 'Option C']

if 'steps' not in st.session_state:
    st.session_state.steps = ['step 1', 'step2', 'step3']   

if 'iteration_count' not in st.session_state:
    st.session_state.iteration_count = 0   

if 'tag_options' not in st.session_state:
    st.session_state.tag_options = []

if 'step_text' not in st.session_state:
    st.session_state.step_text = None

def save_options():
    st.session_state.tag_options.append({st.session_state.step_text: st.session_state.step_options})

selected_tags = ['Option A']

if st.session_state.iteration_count <  3:

    i = st.session_state.iteration_count
    st.session_state.step_text = st.session_state.steps[i] 
    message = f"what are the options for {st.session_state.step_text}?"

    tags = st.markdown(message)

    with st.chat_message('system'):
            
        with st.form(key='tags'):

            options = st.multiselect(
                    '',
                    tags_values,
                    selected_tags,
                    key='step_options'
                        )
            submit_button_tags = st.form_submit_button(label='submit_tags', on_click=save_options)


    st.session_state.iteration_count +=1

with open('options.pkl', 'wb') as f:
    pickle.dump(st.session_state.tag_options, f)

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