Streamlit form resets after toggling input from dropdown in main window after submit

Hi I am running my app locally and am using python v3.11.4 and streamlit version 1.29.0

I am using a form to submit parameters to run LIDA

After I fill out the form and click submit, it generates some data viz plots

After I hit submit, it will list the goals in the dropdown box, as well as different visualizations. However, when I choose a different goal to visualize, everything gets reset.

I am new to session states and forms. I don’t necessarily want to resubmit the form, just want to toggle between the generated goals in the main window dropdown bar after I have initially clicked submit. Can someone help point me in the right direction?

The relevant code:

with st.sidebar:
    with st.form(key='input_form'):
        
        selected_dataset_label = st.selectbox(
            'Choose a dataset',
            options=[dataset["label"] for dataset in datasets],
            index=1
        )
        
        
        selected_dataset = datasets[[dataset["label"]
                                     for dataset in datasets].index(selected_dataset_label)]["url"]

        if not selected_dataset:
            st.info("To continue, select a dataset from the sidebar on the left or upload your own.")
    
   
    
        selected_model = st.selectbox(
            'Choose a model',
            options=models,
            index=0
            )
        temperature = st.slider(
            "Temperature",
            min_value=0.0,
            max_value=1.0,
            value=0.0)
    
        
        use_cache = st.checkbox("Use cache", value=True)
   
   
        num_goals = st.slider(
                "Number of goals to generate",
                min_value=1,
                max_value=10,
                value=4)
    
        
        user_goal = st.text_input("Describe Your Goal")
        
       
        selected_method_label = st.selectbox(
            'Choose a summarization method',
            options=[method["label"] for method in summarization_methods],
            index=0
        )


        selected_method = summarization_methods[[
            method["label"] for method in summarization_methods].index(selected_method_label)]["label"]

        # add description of selected method in very small font to sidebar
        selected_summary_method_description = summarization_methods[[
            method["label"] for method in summarization_methods].index(selected_method_label)]["description"]

        if selected_method:
            st.markdown(
            f"<span> {selected_summary_method_description} </span>",
                unsafe_allow_html=True)

        num_visualizations = st.slider(
                "Number of visualizations to generate",
                min_value=1,
                max_value=3,
                value=2)
        submitted= st.form_submit_button("Submit")
    
    

if submitted:
    

    lida = Manager(text_gen=llm("openai", api_key=openai_key))
    textgen_config = TextGenerationConfig(
        n=1,
        temperature=temperature,
        model=selected_model,
        use_cache=use_cache)
    
    st.write("## Summary")
    


    # **** lida.summarize *****
    summary = lida.summarize(
        selected_dataset,
        summary_method=selected_method,
        textgen_config=textgen_config)

    if "dataset_description" in summary:
        st.write(summary["dataset_description"])

    if "fields" in summary:
        fields = summary["fields"]
        nfields = []
        for field in fields:
            flatted_fields = {}
            flatted_fields["column"] = field["column"]
            # flatted_fields["dtype"] = field["dtype"]
            for row in field["properties"].keys():
                if row != "samples":
                    flatted_fields[row] = field["properties"][row]
                else:
                    flatted_fields[row] = str(field["properties"][row])
            # flatted_fields = {**flatted_fields, **field["properties"]}
            nfields.append(flatted_fields)
        nfields_df = pd.DataFrame(nfields)
        st.write(nfields_df)
    else:
        st.write(str(summary))

    #generate goals

    goals = lida.goals(summary, n=num_goals, textgen_config=textgen_config)
    default_goal = goals[0].question
    goal_questions = [goal.question for goal in goals]

    #append user goal
    if user_goal:
        new_goal = Goal(index=0,question=user_goal, visualization=user_goal, rationale="")
        goals.append(new_goal)
        goal_questions.append(new_goal.question)



    st.write("## Goals")
    #if st.session_state['form_one_complete']:
    
    selected_goal = st.selectbox('Choose a generated goal', options=goal_questions, index=0)
    selected_goal_index = goal_questions.index(selected_goal)
    
    st.write(goals[selected_goal_index])
        
    selected_goal_object = goals[selected_goal_index]

    # visualize goal
    if selected_goal_object:
        st.write("## Visualizations")
        st.write(goal_questions.index(selected_goal))    

        textgen_config = TextGenerationConfig(
                n=num_visualizations, temperature=temperature,
                model=selected_model,
                use_cache=use_cache)

            # **** lida.visualize *****
        visualizations = lida.visualize(
                summary=summary,
                goal=selected_goal_object,
                textgen_config=textgen_config,
                library=selected_library) 
    
        st.write("total visualizations", len(visualizations))   
        viz_titles = [f'Visualization {i+1}' for i in range(len(visualizations))]

        selected_viz_title = st.selectbox('Choose a visualization', options=viz_titles, index=0)
    
        selected_viz = visualizations[viz_titles.index(selected_viz_title)]

        if selected_viz.raster:
            from PIL import Image
            import io
            import base64

            imgdata = base64.b64decode(selected_viz.raster)
            img = Image.open(io.BytesIO(imgdata))
            st.image(img, caption=selected_viz_title, use_column_width=True)

            st.write("### Visualization Code")
            st.code(selected_viz.code)```

That is normal, because that is how streamlit works. If user interacts, it will rerun the code from top to bottom.

There must be a way to improve your app.

Can you include the goals in the form? So that users are only asked once.

Hi @Amit_Indap

You could also look into storing your responses as Session state variables and could also explore using callback functions on the widgets (via on_click or on_click parameters) so that widget interactions would not trigger an app rerun.

More info and example code snippets in the Docs page:

Hope this helps!