How to display with options to select inside button

Hello, my app first takes an input from users, and clicking a “Run” button generates a new selectbox menu to choose from one of the inputs users selected above and display them. However, when the user selects a color to display in selectbox(), what’s inside if st.button('Run') disappears, so that user is never able to display colors other than default value “red”.

Here’s my code:

import streamlit as st

colors = ['red', 'green', 'yellow', 'blue']
color_input = st.multiselect('Select options', colors, colors[:])
if st.button('Run'):
    st.markdown('---')
    col1, col2 = st.columns(2)
    input_one = col1.selectbox('Select Color to display', tuple(color_input))
    col2.write(input_one)

Here’s a step-by-step use case and what I hope to achieve:

  1. User select color options and click “Run”
    image

  2. New menu is generated with default value “red” and text “red” is displayed on the right
    image

  3. However, when user wants to display “green” and selects “green”,
    image

  4. everything disappears and revert back to the state before “Run” is clicked. I would like to have everything to stay there and allow user to display “green” on the right.

image

Try:

import streamlit as st

# init state
if 'btn_clicked' not in st.session_state:
    st.session_state['btn_clicked'] = False


def callback():
    # change state value
    st.session_state['btn_clicked'] = True


colors = ['red', 'green', 'yellow', 'blue']
color_input = st.multiselect('Select options', colors, colors[:])
if st.button('Run', on_click=callback) or st.session_state['btn_clicked']:  # add callback and session judge
    st.markdown('---')
    col1, col2 = st.columns(2)
    input_one = col1.selectbox('Select Color to display', tuple(color_input))
    col2.write(input_one)

reference nested buttons

1 Like

Thanks for your help! Currently, if a user selects an option on col1.selectbox it re-runs the whole code under if st.button...: . I wonder how we could run just the last two lines of code without having to re-run the whole code under if statement? In this reproducible example, it’s not a problem, but I have a heavy code running before input_one = col1.selectbox(...) re-running the whole thing under if statement becomes time-consuming. Thanks so much for your advice :slight_smile:

Once any conponent value change,the streamlit will rerun from top to end.

Find your time-consuming codes,then wrap them into a function, use st.cache decorator on the top of the function.

No st.cache:

import streamlit as st
import time

# init state
if 'btn_clicked' not in st.session_state:
    st.session_state['btn_clicked'] = False


def callback():
    # change state value
    st.session_state['btn_clicked'] = True


def time_consuming_func():
    time.sleep(3)
    return


colors = ['red', 'green', 'yellow', 'blue']
color_input = st.multiselect('Select options', colors, colors[:])
if st.button('Run', on_click=callback) or st.session_state['btn_clicked']:  # add callback and session judge
    time_consuming_func()
    st.markdown('---')
    col1, col2 = st.columns(2)
    input_one = col1.selectbox('Select Color to display', tuple(color_input))
    col2.write(input_one)

no_cache

Use st.cache:

import streamlit as st
import time

# init state
if 'btn_clicked' not in st.session_state:
    st.session_state['btn_clicked'] = False


def callback():
    # change state value
    st.session_state['btn_clicked'] = True


@st.cache
def time_consuming_func():
    time.sleep(3)
    return


colors = ['red', 'green', 'yellow', 'blue']
color_input = st.multiselect('Select options', colors, colors[:])
if st.button('Run', on_click=callback) or st.session_state['btn_clicked']:  # add callback and session judge
    time_consuming_func()
    st.markdown('---')
    col1, col2 = st.columns(2)
    input_one = col1.selectbox('Select Color to display', tuple(color_input))
    col2.write(input_one)

cache

1 Like

Can you create more than one st.cache functions?