Interdependent widgets in forms

Hi everyone,

I am really stoked by the introduction of forms having first discovered the need more than a year ago :grin:And I must say the functionality works splendidly and intuitively out of the box - it took me just a few minutes for each app to start using forms in various places! So big kudos to the Streamlit team with the great functionality and documentation!

The only issue I have encountered, is that it is for obvious reasons a bit clonky to have interdependent widgets in forms, as also stated clearly in the docs.

I was wondering if it was possible to partly circumvent this issue by having a widget visually inside a form, which is not programmatically inside the form. I.e. a widget placed inside the ā€˜form widget’ where changing its values should cause reruns. I tried a bit myself without luck and I’m guessing it is not possible - but perhaps someone has already figured out a workaround? Thus far, my ā€˜workaround’ is to click the submit button twice :sweat_smile:

Best regards,
Peter

1 Like

Glad you like the feature @PeterT! I have no idea the answer here, but I’ll pass this feedback along to the product team in general about interdependent widgets :slight_smile:

Best,
Randy

@PeterT : Thanks for sharing your feedback! As of now, we don’t allow for interdependent widgets by design. We made this decision to simplify forms in v1.

Our focus in the near term is:

  1. To keep the API/feature relatively stable and fix bugs/errors
  2. See how the community uses st.forms and collect additional use cases

Can you please share your use case for ā€œhaving a widget visually inside a form, which is not programmatically inside the formā€ ? - It would be useful for us to keep in mind as we think about what to build in forms in the next version. Thanks!

Hi @abhi and Randy

Thanks for getting back to me.

Completely understand the focus you have.

To elaborate on what I need, I’ve prepared a minimal example. This example is a bit contrived, as the layout here looks fine, but when you have a large form and the interdependent widgets are somewhere in the middle, the problem is more real. But I hope the example here makes it more clear what I mean. I am interested in the functionality from example 1 with the layout from example 2 below.

import streamlit as st
import pandas as pd
import numpy as np

@st.cache
def filter_df(df, column, min_value, max_value, default_min=0, default_max=100):
    if min_value != default_min or max_value != default_max:
        filter = (df[column] >= min_value) & (df[column] <= max_value)
        df = df[filter]
    return df

st.title("Example 1")
df = pd.DataFrame({"A" : np.arange(100), "B": np.arange(100), "C": np.arange(100)})

## With not so nice layout but right functionality
options = st.multiselect("Select columns", options=["A","B", "C"])
with st.form(key="example_1"):
    sliders = {option : st.slider(option, min_value=0, max_value=100, value=(0,100)) for option in options}
    st.form_submit_button("Submit")

# Here we apply filter from all sliders on the DF. This is potentially an expensive operation
# with large dfs, thus we want to use a form for the sliders
for column, (min_value, max_value) in sliders.items():
    df = filter_df(df, column, min_value, max_value)

st.write(df)

st.title("Example 2")
df = pd.DataFrame({"A" : np.arange(100), "B": np.arange(100), "C": np.arange(100)})

## With nice layout but needs to "double click" submit
with st.form(key="example_2"):
    options = st.multiselect("Select columns", options=["A","B", "C"])
    sliders = {option : st.slider(option, min_value=0, max_value=100, value=(0,100)) for option in options}
    st.form_submit_button("Submit")

# Here we apply filter from all sliders on the DF. This is potentially an expensive operation
# with large dfs, thus we want to use a form for the sliders
for column, (min_value, max_value) in sliders.items():
    df = filter_df(df, column, min_value, max_value)

st.write(df)

Best,
Peter

facing the same issue man. I’ve a form which takes a file & seperator, then produces a pandas profile and ANOTHER form which is a selectbox (with options as df.columns from the file). Once I submit the 2nd form the whole app is re-run.