How to dynamically create a number of columns and insert an element into each

My app would involve allowing the user to choose the number of inputs he wishes to enter
For example, at the top, there would be a select box asking the user for the number of inputs, say 1 to 5, I’ll call this n_input.

And then, I would like there to be that number of select boxes to show up. So for example, the user selected “3” in the previous n_input select box, then 3 select boxes would show up which allow the user to input 3 items.

This is not that difficult to accomplish:
for i in range(n_input):
input[i]=st.selectbox("Input # "+str(i),[1,2,3],key=i)

However, I don’t know how to pack them into columns instead of just lining up vertically. The number of variables to unpack ranges from 1 to 7 so this requires some dynamic assignment.

columns[1],columns[2],.....columns[n_words]=st.beta_columns(nwords)

Surely, I could make a big if loop,

if n_input==7:
     columns[1],columns[2],...,columns[7]=st.beta_columns(7)
if n_input==6:
     columns[1],columns[2],...,columns[6]=st.beta_columns(6)
if n_input==5:
     columns[1],columns[2],...,columns[5]=st.beta_columns(5)
....

Is there a better way to do this?

Hi @terbiume65, welcome to the Streamlit community!

You can accomplish what you are talking about using the following:

import streamlit as st


ncol = st.sidebar.number_input("Number of dynamic columns", 0, 20, 1)
cols = st.beta_columns(ncol)

for i, x in enumerate(cols):
    x.selectbox(f"Input # {i}",[1,2,3], key=i)

Best,
Randy

2 Likes

Hi, just to follow up, is there any way to set a max number of columns (e.g. 3) to show per row? Say if I have three items to show, they’ll be on the same row, but if there’re 5 items, they’ll be split into two rows, 7 items 3 rows, etc?
Thanks!

Hi Hurley,

You can use the Python’s modulo operator to do the wrapping. The modulo operator (%) returns the remainder of 2 numbers e.g. 5%3 returns 2 which would put the fifth element in the second column of the second row.

import streamlit as st

ncol = st.sidebar.number_input("Number of columns", 0, 20, 1)
wcol = st.sidebar.number_input("Wrap at column", 1, 3, 1)

cols = st.columns(ncol)

for i in range(ncol):
    col = cols[i%wcol]
    col.selectbox(f"Input # {i}",[1,2,3], key=i)
4 Likes

Hi @hudgeon,

Is there a way to accomplish this without the selectbox, but with graphs instead.

For example:

ncol = count_trues #(which is the number trues in a dataframe column)
wcol = 5

cols = st.columns(ncol)

for i in range(ncol):
      col = cols[i%wcol]
      with col:
          #my graphs

Thanks!