Multiselect and Download button reload the page

Hi,

I have developed a Streamlit application (locally) featuring 5 multiselect widgets (Families, Sub-Families, Products, Regions, & Bakeries), two date inputs (Start Date and End Date), and a slider for selecting times between 00:00 to 23:59. My application generates a DataFrame based on the filters applied via these multiselect widgets using a function named generate_fact_ventes(). After generating the DataFrame, an option to “Download data as Excel” is provided.

Here’s the workflow issue I’m facing:

When a Family is selected, the options in the Sub-Families and Products multiselects are supposed to update dynamically. This is handled by two functions: generate_products() and generate_sub_family(), which take the selected Family as their argument.

A similar principle applies when selecting a Sub-Family; the Products multiselect updates its options accordingly.

The same logic is used for Bakeries; selecting a Region filters the Bakeries multiselect to only show options that belong to that selected Region.

However, I’m encountering a significant issue: every interaction with the multiselects, date inputs, or the slider triggers what seems to be a page reload. Initially, I considered encapsulating my components within a form to prevent this, but then my functions only get called upon submitting the form, which is not practical for my needs.

Furthermore, clicking the button to download the Excel file causes the application to reload from the beginning, although the selections in the multiselect widgets are preserved.

This behavior creates a disruptive experience for the users. How can I resolve these issues to prevent the apparent page reloads on interactions and ensure a smoother user experience?


start_date = col2.date_input(
        "Date début",
        min_value=pd.to_datetime("1900-01-01").date(),
        max_value=pd.to_datetime("2100-01-01").date(),
        value=default_start_date,
    )
end_date = a2.date_input(
        "Date fin",
        min_value=pd.to_datetime("1900-01-01").date(),
        max_value=pd.to_datetime("2100-01-01").date(),
        value=default_start_date,
    )
# Options pour la sélection de période ==> Surement à remettre en place pour check cette histoire de .split(" ")[-1]
# period_options = []
# for _, row in dim_periode.iterrows():
#     start_time = str(row["heuredebut"]).split(" ")[-1]
#     period_options.append(f"{start_time}")

period_options=load_data(query_dim_periode, engineSnow, "heuredebut")  # Adaptation si nécessaire pour le formatage des heures
# Options pour la sélection de boulangeries
boulangerie_options = load_data(query_dim_boulangerie,engineSnow,'nomusuel')
# #Options pour la sélection de familles
famille_options=load_data(query_dim_famille,engineSnow,'nomfamille')
# #Options pour la sélection de sous familles
sous_famille_options=load_data(query_dim_sous_famille,engineSnow,'nomsousfamille')
# # Options pour la sélection de produits
produit_options=load_data(query_dim_produit,engineSnow,'designation')
# # Options pour la sélection de régions
region_options=load_data(query_dim_region,engineSnow,'libellezone')

appointment = b2.slider(
            "Choix intervalle:",
            value=(tt(00, 00), tt(23, 59,59,999999)),
            step = timedelta(minutes=30)
        )
famille_selected = tuple(col1.multiselect( 
        "Sélection famille(s)",
        famille_options,
        placeholder='Choix famille(s)'
        
    ))
sous_famille_selected = tuple(a1.multiselect( 
            "Sélection sous famille(s)",
            generate_sous_familles(famille_selected,engine),
            placeholder='Choix sous famille(s)'
        ))
produit_selected = tuple(b1.multiselect( 
        "Sélection produit(s)",
        generate_produit(famille_selected,sous_famille_selected,engine),
        placeholder='Choix produit(s)'
    ))

region_selected= tuple(col3.multiselect( 
        "Sélection région(s)",
        region_options,
        placeholder='Choix région(s)'

    ))
boulangerie_selected = tuple(
        a3.multiselect("Sélection boulangerie(s)",
        generate_boulangeries(region_selected,engine),
        placeholder="Choix boulangerie(s)"
)
        
    )


if st.button("Calculer"):

    fact_ventes_30=generate_fact_ventes_30(start_date,end_date,appointment[0],appointment[1],boulangerie_selected,region_selected,produit_selected,sous_famille_selected,famille_selected)
	# Code ...
	# Code ...
	# Code ..
	xlsx_binary = BytesIO()
    fact_ventes_30.to_excel(xlsx_binary, index=False, engine='openpyxl')
   
    # Provide a download button
    st.download_button(
        label="Download data as Excel",
        data=xlsx_binary.getvalue(),
        file_name="fact_produits_30min_"+"_".join(boulangerie_selected)+"_"+str(start_date)+"_to_"+str(end_date)+".xlsx",
        key='download-excel'
    )
 
    

Thank you in advance for your assistance

Have a look in our guide to post an effective question.