Search code examples
pythonstreamlitvariable-variablesdynamic-ui

Streamlit dynamic UI to generate dynamic input widgets depending on value from a different input widget


I want to open this post as I can't find anything on the official documentation from streamlit or any resources that mentioned how to do this. After some trial and error I have figured out a way, and will post the answer below. This is a function that in R shiny is called dynamic UI, here's the question.

How to generate dynamic input widgets depending on the value from a different input widget? For example see below picture, the numbers of text_input called Product Code i depends on the value from the number_input called Number of Products. So if there are x number of products, there will be x number of text_input generated dynamically. Moreover, the value inside the generated text_input can be extracted as well.

enter image description here


Solution

  • Here is one way to do this.
    First, use list comprehension to store keys (variables to use to extract values from text_input later) and values (text_input).
    Next, use key and value to set the attribute in a class.
    The value from text_input labelled as product2 can be extracted using the attribute within the class using p.product2 for example.

    import streamlit as st
    
    number_of_products = st.sidebar.number_input(label="Number of Products",
                                         min_value=0, max_value=20, value=1)
    
    class Products:
        pass
    
    p = Products()
    keys = [str("product"+str(x+1)) for x in range(number_of_products)]
    values = [st.sidebar.text_input(label=f"Product Code {x+1}", value=0) for x in range(number_of_products)]
    
    for key, value in zip(keys, values):
        setattr(p, key, value)
    
    # each key's value is stored in the class as an attribute
    st.write(p.product2)
    

    Using dictionary and exec command can also dynamically declare variables, but when the value inside the text_input is not a number, it will generate an error.