I noticed a weird behaviour of query_params with the version 0.89
The query params keep resetting to the previous value, the user has to click twice to update the params. Verified that this works properly with versions 0.88 or lower
With version 0.89:
With version 0.88:
My MultiPage framework:
import streamlit as st
class MultiPage:
def __init__(self):
self.apps = []
self.app_names = []
self.default = ''
def add_app(self, title, func, args=None):
self.app_names.append(title)
self.apps.append({
"title": title,
"function": func,
"args":args
})
def run(self):
# get query_params
query_params = st.experimental_get_query_params()
self.default = query_params["app"][0] if "app" in query_params else None
default_index = self.app_names.index(self.default) if self.default else 0
# simple radio button for navigation
app = st.sidebar.radio(
'Go To',
self.apps,
index = default_index,
format_func=lambda app: app['title'],
key = 'Navigation')
# reflect the current app in query_params
self.default = app['title']
st.experimental_set_query_params(app=self.default)
# runs the selected app with passes args
app['function'](app['args'])
st.radio doesn’t return an object, it returns the selection as a string. So you need to resolve the selection to the corresponding app object. The code below works fine, including changing the page directly via the URL app query param. I also quoted and unquoted the URL params just in case.
Having said that, the double click issue remains in v0.89 Hopefully, @Charly_Wargnier can get it looked at by one of the engineers.
import streamlit as st
import urllib
class MultiPage:
def __init__(self):
self.apps = []
self.app_names = []
self.current_app_name = None
def add_app(self, title, func, *args, **kwargs):
self.app_names.append(title)
self.apps.append({
"title": title,
"function": func,
"args":args,
"kwargs":kwargs
})
def run(self, label='Go To'):
# make correct app selection from query param
query_params = st.experimental_get_query_params()
app_name = urllib.parse.unquote(query_params["app"][0]) if "app" in query_params else None
self.current_app_name = app_name if app_name in self.app_names else None
current_app_name_index = self.app_names.index(self.current_app_name) if self.current_app_name else 0
# configure radio buttons for app navigation
app_choice = st.sidebar.radio(
label,
self.app_names,
index = current_app_name_index,
key = 'Navigation')
app = self.apps[self.app_names.index(app_choice)]
# update current app name and query param from app choice
self.current_app_name = app['title']
# runs the selected app passing args/kwargs
app['function'](self.current_app_name, *app['args'], **app['kwargs'])
st.experimental_set_query_params(app=urllib.parse.quote(self.current_app_name))
def app1(title, info=None):
st.title(title)
st.write(info)
def app2(title, info=None):
st.title(title)
st.write(info)
def app3(title, info=None):
st.title(title)
st.write(info)
mp = MultiPage()
mp.add_app('Application 1', app1, info='Hello from App 1')
mp.add_app('Application 2', app2, info='Hello from App 2')
mp.add_app('Application 3', app3, info='Hello from App 3')
mp.run('Launch application')
Maybe the dev team (via @snehankekre, @Charly_Wargnier) can update the docs if arbitrary collections are indeed returned, which makes sense when a format_func is supplied. (One could always look at the source code in GitHub TBH.)
@akshanshkmr - I liked your update as it leverages the auto-created session state for widgets. Here’s a full working version so the Streamlit community can cut-and-paste and run it. Can you please mark this as the solution?
import streamlit as st
class MultiPage:
def __init__(self):
self.apps = []
self.app_names = []
def add_app(self, title, func, *args, **kwargs):
self.app_names.append(title)
self.apps.append({
"title": title,
"function": func,
"args":args,
"kwargs": kwargs
})
def run(self, label='Go To'):
# common key
key='Navigation'
# get app choice from query_params
query_params = st.experimental_get_query_params()
query_app_choice = query_params['app'][0] if 'app' in query_params else None
# update session state (this also sets the default radio button selection as it shares the key!)
st.session_state[key] = query_app_choice if query_app_choice in self.app_names else self.app_names[0]
# callback to update query param from app choice
def on_change():
params = st.experimental_get_query_params()
params['app'] = st.session_state[key]
st.experimental_set_query_params(**params)
app_choice = st.sidebar.radio(label, self.app_names, on_change=on_change, key=key)
# run the selected app
app = self.apps[self.app_names.index(app_choice)]
app['function'](app['title'], *app['args'], **app['kwargs'])
def app1(title, info=None):
st.title(title)
st.write(info)
def app2(title, info=None):
st.title(title)
st.write(info)
def app3(title, info=None):
st.title(title)
st.write(info)
mp = MultiPage()
mp.add_app('Application 1', app1, info='Hello from App 1')
mp.add_app('Application 2', app2, info='Hello from App 2')
mp.add_app('Application 3', app3, info='Hello from App 3')
mp.run('Launch application')
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.