How to keep widget value remembered in Multi-page app when switching pages using a streamlit button

Hi,

I have developed a multi-page app using native functionality of Streamlit. Most of the pages have inputs widgets which automatically set to default value if I switch pages using the button in bottom left/right.

I attached an example of this case to demonstrate my problem.

Image 1: (Deafult widget behaviour)

Image 2: (Doing some changes)

Image 3: (Navigating back to the same page from another page)

** I used Switch page function as described here

**Also used streamlit-ext to stop whole script from rerunning when widget value changes

Let me know if someone has a solution in mind.

Best,
Debayan

2 Likes

@DebayanPaul93 This is a known issue for some use-cases, and we’re considering some changes to the API to make this easier to resolve. For now, though, if you add this to the top of each page in your multipage app, it should preserve the state of your widgets across pages:

for k, v in st.session_state.items():
    st.session_state[k] = v
1 Like

Hi, @blackary , should I insert this inside the function def paper_input() or after the imports/ somewhere else?

Here is my code snippet of the page:

import streamlit as st,pandas as pd,os, math
import streamlit_ext as ste
from streamlit_extras.switch_page_button import switch_page
from streamlit_extras.add_vertical_space import add_vertical_space

st.markdown(st.session_state.style, unsafe_allow_html=True)
st.write('<style>div.block-container{padding-top:2rem;}</style>', unsafe_allow_html=True)
st.markdown(st.session_state.paddingstyle, unsafe_allow_html=True)
#Add Logo
st.markdown(
        f"""
        <style>
            [data-testid="stSidebarNav"] {{
                background-image: url({"https://www.metamorfoze.nl/themes/custom/metamorfoze/static/images/logo_m.png"});
                background-repeat: no-repeat;
                padding-top: 150px;
                background-position: 20px 20px;
            }}
        </style>
        """,
        unsafe_allow_html=True,
    )


#user input

def paper_input():
	list_pH,list_intdp=[],[]
	original_title = '<p style="font-family:Sans serif; font-size: 30px;"><b>Collection Objects Details</b></p>'
	st.markdown(original_title, unsafe_allow_html=True)
	col1, col2, col3, col4 = st.columns(4)
	with col1:
		objectno = ste.number_input("Enter number of type of objects",1,4,key='noofobjecttype')
	for counter in range (objectno):
		if(objectno>1):
			st.markdown("#### Type {} Object Chemical Properties".format(counter+1))
			colc, cold = st.columns(2)
			with colc:
				pH = ste.slider("Select pH level",min_value=3,max_value=9,value=8,step=1,key='ph{}'.format(counter+2))
			with cold:
				int_dp = ste.slider("Select Initial DP",min_value=500,max_value=2500,value=1200,step=50,key='dp{}'.format(counter+2))

			if isinstance(pH, tuple):
				pH = pH[0]
			if isinstance(int_dp, tuple):
				int_dp = int_dp[0]

			list_pH.append(pH)
			list_intdp.append(int_dp)

		else:
			st.markdown("#### Object Chemical Properties")
			cola, colb = st.columns(2)
			with cola:
				pH = ste.slider("Select pH level",min_value=3,max_value=9,value=8,step=1,key='ph1')
			with colb:
				int_dp = ste.slider("Select Initial DP",min_value=500,max_value=2500,value=1200,step=50,key='dp1')

			if isinstance(pH, tuple):
				pH = pH[0]
			if isinstance(int_dp, tuple):
				int_dp = int_dp[0]

			list_pH.append(pH)
			list_intdp.append(int_dp)

	add_vertical_space(3)
	original_title = '<p style="font-family:Sans serif; font-size: 30px;"><b>Critical DP of Collection</b></p>'
	st.markdown(original_title, unsafe_allow_html=True)
	col10, col11, col12 = st.columns(3)
	with col10:
		crit_dp = ste.slider("Select Critical DP",min_value=200,max_value=400,step=50,key='critdp')
		if isinstance(crit_dp, tuple):
			crit_dp = crit_dp[0]

	add_vertical_space(5)
	col1, col2, col3, col4, col5 = st.columns(5)
	with col1:
		prev_page = st.button("Previous Page<Weather Data")
	with col3:
		save_button = st.button("Save Inputs")
	with col5:
		next_page = st.button("Next Page>Repository Sizing")


	if prev_page:
		switch_page("Weather Data")
	if save_button:
		valuelist = [objectno,list_pH,list_intdp,crit_dp]
		columnlist = ['Number of object types', 'List of pH Values', 'List of Initial DP Values', 'Critical DP']


		#Current working directory
		cwd = os.getcwd()
		#set path to subdirectory and inputfilename
		inputfilesnamewithpath = cwd+'\\Inputfiles\\PaperUserInputs.csv'

		#Write the inputs to a csv file
		inputdf = pd.DataFrame([valuelist], columns = columnlist)

		inputdf.to_csv(inputfilesnamewithpath, index=False)
	if next_page:
		switch_page("Repository Sizing")

paper_input()
1 Like

Right after the imports on each page

Hi @blackary, thanks, the solution seems to working for now. One last question regarding this, is it possible to access any of these session states for using across pages, as I don’t know their key names and also delete all of them at once alter when using the application is done?

You won’t be able to use them easily unless you set the key names yourself, which you can do by just adding key=<whatever> in the widgets themselves.

You can delete them from session state just like it’s a normal dictionary del st.session_state[<key>]

By the way, I noticed you’re adding an app logo in your sidebar – FYI, there is now a dedicated extra for that https://extras.streamlit.app/App%20logo

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.