Streamlit selectbox

Hi,

I am trying to create a simple PLM page, where i am facing issue in dependent selectbox,
where value are populating after i click submit.

Request help to check where i am going wrong.

import streamlit as st
import pandas as pd

st.set_page_config(layout="wide")

if "style_data" not in st.session_state:
    st.session_state.style_data = []

if "product" not in st.session_state:
    st.session_state.product = None

if "product_class" not in st.session_state:
    st.session_state.product_class = None

def new_styles(brand, brick, product, product_class):
    brand = st.session_state.brand
    brick = st.session_state.brick
    product = st.session_state.product
    product_class = st.session_state.product_class
    
    st.session_state.style_data.append(
        {
            "brand": brand,
            "brick": brick,
            "product": product,
            "product_class": product_class
        }
    )

with st.form("new_styles", clear_on_submit=True):
    brand_list = ["ABC"]
    brick_list = ['', 'Kurta', 'Sarees', 'Chudidar Set', 'Chudidar']
    product_list = {'Chudidar Set': ['Chudidar Set', 'Winter Chudidar Set'], 'Sarees': ['Sarees'],
                    'Kurta': ['Kurta', 'Winter Kurta'], 'Chudidar': ['Chudidar', 'Chudi']}
    class_list = {'Chudidar Set': 'Set', 'Sarees': 'Set', 'Kurta': 'Top Wear', 'Chudidar': 'Bottom Wear'}

    brand_col, brick_col, product_col, class_col = st.columns(4)

    with brand_col:
        brand = st.selectbox("BRAND:", brand_list, key="brand")

    with brick_col:
        brick = st.selectbox("BRICK:", brick_list, key="brick")

    with product_col:
        st.session_state.product = product_list.get(brick, "")
        product = st.selectbox("PRODUCT:",st.session_state.product)

    with class_col:
        st.text("CLASS:")
        st.text(class_list.get(brick, ""))
        product_class = (class_list.get(brick, ""))

    
    st.write(brand, brick, product, product_class)


    st.form_submit_button("Submit", on_click=new_styles, args=(brand, brick, product, product_class))

What issue are you facing?

not able select dropdown for product and class

That is because st.session_state.product is an empty string. So the selectbox options list is empty, which automatically disables it.

after commenting, still i am not able select.

import streamlit as st
import pandas as pd

st.set_page_config(layout="wide")

if "style_data" not in st.session_state:
    st.session_state.style_data = []


# if "product" not in st.session_state:
#     st.session_state.product = None

# if "product_class" not in st.session_state:
#     st.session_state.product_class = None

def new_styles(brand, brick, product, product_class):
    brand = st.session_state.brand
    brick = st.session_state.brick
    product = st.session_state.product
    product_class = st.session_state.product_class
    
    st.session_state.style_data.append(
        {
            "brand": brand,
            "brick": brick,
            "product": product,
            "product_class": product_class
        }
    )

with st.form("new_styles", clear_on_submit=True):
    brand_list = ["ABC"]
    brick_list = ['', 'Kurta', 'Sarees', 'Chudidar Set', 'Chudidar']
    product_list = {'Chudidar Set': ['Chudidar Set', 'Winter Chudidar Set'], 'Sarees': ['Sarees'],
                    'Kurta': ['Kurta', 'Winter Kurta'], 'Chudidar': ['Chudidar', 'Chudi']}
    class_list = {'Chudidar Set': 'Set', 'Sarees': 'Set', 'Kurta': 'Top Wear', 'Chudidar': 'Bottom Wear'}

    brand_col, brick_col, product_col, class_col = st.columns(4)

    with brand_col:
        brand = st.selectbox("BRAND:", brand_list, key="brand")

    with brick_col:
        brick = st.selectbox("BRICK:", brick_list, key="brick")

    with product_col:
        st.session_state.product = product_list.get(brick, "")
        product = st.selectbox("PRODUCT:",st.session_state.product)

    with class_col:
        st.text("CLASS:")
        st.text(class_list.get(brick, ""))
        product_class = (class_list.get(brick, ""))

    
    st.write(brand, brick, product, product_class)

@Goyo, Initially, i have created without form it was working fine.
Now modified the code and included under form is it because of that.

Yes, because when you modify a widget, the updated return value is not available until the app reruns or in the callback. But, if the widget is inside a form, there will be no rerun and it cannot have a callback, so you cannot have the updated values until the submit button is pressed.

If you want changes in an input widget to have an immediate effect in the application, don’t put the widget in a form.

@Goyo, Got it. But is there any other way, i can achieve it. Because once i get the input from user. i need display the user input into table (multiple records) and save button to insert the data to the table.

Another way to achieve what? You don’t need a form in order to get the input from the user.

@Goyo , Form allows me select the values from dropdown and once i submit i displaying the input row in the table.

if don’t use form, it rerun’s and unable to display in the table.

I don’t understand why a rerun would prevent you from displaying the table. The data is still there in st.session_state.style_data, IIUC.

1 Like

@Goyo, Thanks for response.

i found similar question asked.

Similar question and similar answer: don’t use a form for that.

Here is an approach without using a form. I make some reformatting, comments, etc.

Complete code

"""Build tables from user selections."""


import streamlit as st
from streamlit import session_state as ss


st.set_page_config(layout="wide")


# Constants
BRAND_LIST = ["ABC"]
BRICK_LIST = ['', 'Kurta', 'Sarees', 'Chudidar Set', 'Chudidar']
PRODUCT_LIST = {
    'Chudidar Set': ['Chudidar Set', 'Winter Chudidar Set'],
    'Sarees': ['Sarees'],
    'Kurta': ['Kurta', 'Winter Kurta'],
    'Chudidar': ['Chudidar', 'Chudi']
}
CLASS_LIST = {
    'Chudidar Set': 'Set',
    'Sarees': 'Set',
    'Kurta': 'Top Wear',
    'Chudidar': 'Bottom Wear'
}


# Session variables
if "style_data" not in ss:
    ss.style_data = []

if "product_class" not in ss:
    ss.product_class = ''


# Functions
def new_styles_cb():
    """Append data to style_data from selection."""
    ss.style_data.append(
        {
            "brand": ss.brand,
            "brick": ss.brick,
            "product": ss.product,
            "product_class": ss.product_class
        }
    )


def build_table():
    """Build table via user inputs"""
    # User selections
    with st.container(border=True):
        st.subheader('Select')

        brand_col, brick_col, product_col, class_col = st.columns(4)

        with brand_col:
            st.selectbox("BRAND:", BRAND_LIST, key="brand")

        with brick_col:
            st.selectbox("BRICK:", BRICK_LIST, key="brick")

        with product_col:
            st.selectbox(
                label="PRODUCT:",
                options=PRODUCT_LIST.get(ss.brick, ['']),
                key='product'
            )

        with class_col:
            st.text("CLASS:")
            ss.product_class = (CLASS_LIST.get(ss.brick, ''))
            st.text(ss.product_class)
            
        # Access the values of selectbox thru the keys.
        st.write(f'{ss.brand}, {ss.brick}, {ss.product}, {ss.product_class}')

        # Our callback new_styles_cb does not need any arguments
        # because we use the state variable values via its keys.
        st.button('Submit', on_click=new_styles_cb)

    # Show the table.
    with st.container(border=True):
        st.subheader('Style Attributes Data table')
        st.dataframe(ss.style_data, width=600)


def main():
    build_table()


if __name__ == '__main__':
    main()

Sample output

1 Like

@ferdy , Thank You

1 Like

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