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.

@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

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