Using radio and multiselect within a form

Summary

Hi all,

Iโ€™m attempting to get a multiselect box to pop up inside a form after making a selection with a radio button.

Steps to reproduce

Code snippet:

import streamlit as st
import pandas as pd

if "df" not in st.session_state:
    data = {
        "year": [2023, 2023, 2023, 2022, 2022, 2022, 2022, 2022, 2022],
        "segment": ["a", "b", "c", "a", "b", "c", "d", "e", "f"],
        "color": [
            "red",
            "black",
            "white",
            "blue",
            "blue",
            "red",
            "red",
            "green",
            "yellow",
        ],
    }
    st.session_state.df = pd.DataFrame(data)

df = st.session_state.df

# User parameter selection
with st.form("my_form"):
    col1, col2, col3 = st.columns(3)
    min_results = 1
    max_results = 20
    select_results = col1.number_input(
        "Select Number of Results",
        min_results,
        max_results,
        value=20,
        help=f"Select number between {min_results} and {max_results}",
    )
    select_sales_volume = col2.number_input("Select Minimum Sales Volume", 1, step=1)
    select_opt_metric = col3.selectbox("Select Optimization Metric", ["A", "B", "C"])

    col4, col5, col6 = st.columns(3)
    select_years = col4.radio("Select Model Years", ("All", "Subset"))
    select_segments = col5.radio("Select Segments", ("All", "Subset"))
    select_colors = col6.radio("Select Colors", ("All", "Subset"))

    col7, col8, col9 = st.columns(3)
    if select_years == "Subset":
        selected_years = col7.multiselect(
            "Select Model Years",
            sorted(df.year.unique()),
            default=sorted(df.year.unique())[0],
        )
        if not selected_years:
            st.warning("Select at least one model year", icon="โš ๏ธ")

    if select_segments == "Subset":
        selected_segments = col8.multiselect(
            "Select Segments",
            sorted(df["segment"].unique()),
            default=sorted(df["segment"].unique())[0],
        )
        if not selected_segments:
            st.warning("Select at least one segment", icon="โš ๏ธ")

    if select_colors == "Subset":
        selected_colors = col9.multiselect(
            "Select Colors",
            sorted(df.color.unique()),
            default=sorted(df.color.unique())[0],
        )
        if not selected_colors:
            st.warning("Select at least one color", icon="โš ๏ธ")

    submitted = st.form_submit_button("Submit")
    submitted


If applicable, please provide the steps we should take to reproduce the error or specified behavior.

Expected behavior:

When selecting Subset in the radio button, a multiselect box should appear.

Actual behavior:

When selecting Subset in the radio button, the multiselect box does not appear.

Debug info

  • Streamlit version 1.18.1

Here is an example that doesnโ€™t use st.form:

import streamlit as st
import pandas as pd
from st_aggrid import GridOptionsBuilder, AgGrid

if "df" not in st.session_state:
    data = {
        "year": [2023, 2023, 2023, 2022, 2022, 2022, 2022, 2022, 2022],
        "segment": ["a", "b", "c", "a", "b", "c", "d", "e", "f"],
        "color": [
            "red",
            "black",
            "white",
            "blue",
            "blue",
            "red",
            "red",
            "green",
            "yellow",
        ],
    }
    st.session_state.df = pd.DataFrame(data)

df = st.session_state.df

# User parameter selection
col1, col2, col3 = st.columns(3)
min_results = 1
max_results = 20
select_results = col1.number_input(
    "Select Number of Results",
    min_results,
    max_results,
    value=20,
    help=f"Select number between {min_results} and {max_results}",
)
select_sales_volume = col2.number_input("Select Minimum Sales Volume", 1, step=1)
select_opt_metric = col3.selectbox("Select Optimization Metric", ["A", "B", "C"])

col4, col5, col6 = st.columns(3)
select_years = col4.radio("Select Model Years", ("All", "Subset"))
select_segments = col5.radio("Select Segments", ("All", "Subset"))
select_colors = col6.radio("Select Colors", ("All", "Subset"))

col7, col8, col9 = st.columns(3)
if select_years == "Subset":
    selected_years = col7.multiselect(
        "Select Model Years",
        sorted(df.year.unique()),
        default=sorted(df.year.unique())[0],
    )
    if not selected_years:
        st.warning("Select at least one model year", icon="โš ๏ธ")

if select_segments == "Subset":
    selected_segments = col8.multiselect(
        "Select Segments",
        sorted(df["segment"].unique()),
        default=sorted(df["segment"].unique())[0],
    )
    if not selected_segments:
        st.warning("Select at least one segment", icon="โš ๏ธ")

if select_colors == "Subset":
    selected_colors = col9.multiselect(
        "Select Colors",
        sorted(df.color.unique()),
        default=sorted(df.color.unique())[0],
    )
    if not selected_colors:
        st.warning("Select at least one color", icon="โš ๏ธ")

if st.button("Submit"):
    grid_df = df
    if len(grid_df) == 0:
        st.info("Selection has no data, please try another selection.")
    else:
        gb = GridOptionsBuilder.from_dataframe(grid_df)
        gb.configure_pagination(
            paginationAutoPageSize=False, paginationPageSize=10
        )
        grid_options = gb.build()
        grid_response = AgGrid(
            grid_df,
            gridOptions=grid_options,
            fit_columns_on_grid_load=False,
            theme="material",
            width="100%",
            allow_unsafe_jscode=True,
            enable_enterprise_modules=True,
        )

The issue Iโ€™m having with this version of the code is the AG Grid disappears when you click on the column sort.

hi @steffrees try this once

import streamlit as st
import pandas as pd

if "df" not in st.session_state:
    data = {
        "year": [2023, 2023, 2023, 2022, 2022, 2022, 2022, 2022, 2022],
        "segment": ["a", "b", "c", "a", "b", "c", "d", "e", "f"],
        "color": [
            "red",
            "black",
            "white",
            "blue",
            "blue",
            "red",
            "red",
            "green",
            "yellow",
        ],
    }
    st.session_state.df = pd.DataFrame(data)

df = st.session_state.df

# User parameter selection
with st.form("my_form"):
    col1, col2, col3 = st.columns(3)
    min_results = 1
    max_results = 20
    select_results = col1.number_input(
        "Select Number of Results",
        min_results,
        max_results,
        value=20,
        help=f"Select number between {min_results} and {max_results}",
    )
    select_sales_volume = col2.number_input("Select Minimum Sales Volume", 1, step=1)
    select_opt_metric = col3.selectbox("Select Optimization Metric", ["A", "B", "C"])

    col4, col5, col6 = st.columns(3)
    select_years = col4.radio("Select Model Years", ("All", "Subset"))
    select_segments = col5.radio("Select Segments", ("All", "Subset"))
    select_colors = col6.radio("Select Colors", ("All", "Subset"))

    # Move multiselect boxes outside the form
    selected_years = []
    selected_segments = []
    selected_colors = []

    if select_years == "Subset":
        selected_years = st.multiselect(
            "Select Model Years",
            sorted(df.year.unique()),
            default=sorted(df.year.unique())[0],
        )
        if not selected_years:
            st.warning("Select at least one model year", icon="โš ๏ธ")

    if select_segments == "Subset":
        selected_segments = st.multiselect(
            "Select Segments",
            sorted(df["segment"].unique()),
            default=sorted(df["segment"].unique())[0],
        )
        if not selected_segments:
            st.warning("Select at least one segment", icon="โš ๏ธ")

    if select_colors == "Subset":
        selected_colors = st.multiselect(
            "Select Colors",
            sorted(df.color.unique()),
            default=sorted(df.color.unique())[0],
        )
        if not selected_colors:
            st.warning("Select at least one color", icon="โš ๏ธ")

    submitted = st.form_submit_button("Submit")
    submitted