I have an app with three tabs, and some buttons in the sidebar. When a button is clicked, running a function and processing some things in session_state, the app will always return to the first tab, when I would prefer it to remain on the tab that was open when the process was run.
@altanner Unfortunately, as st.tabs works today itâs purely a visual component and thereâs no way to interact with it programmatically (e.g. to see which tab was clicked, or force a certain tab to be clicked). The simplest alternative I can recommend is to swap out tabs with something like a selectbox, which by default saves its state between app runs.
Thanks for your ongoing help and information @blackary !
Hope this becomes something that Streamlit implement. Itâs not a real biggie, but for my app I am trying to make it so users can flit between tabs for different views of their data, plus have action buttons which are always visible in the sidebar. Will keep my eyes open for future updates.
Feel free to put a request for this functionality on Issues ¡ streamlit/streamlit ¡ GitHub â I know a number of people have mentioned this idea on the forum, but I donât think I see an issue requesting this functionality currently on github.
Well, I think of doing that, but then go âcrikey 526 issues⌠I donât want to pile on even more⌠and itâll just get lost and forgotten in this avalanche anywayâ.
But maybe that is normal for a repo? I get anxiety issues if I have more than 2 or 3 issues on a repo. Is trillions of issues just how things work?
It depends what you compare it to. I think for large OSS projects that have a large userbase, having a large number of open issues is fairly normal (see Issues ¡ matplotlib/matplotlib ¡ GitHub for example). That being said, the streamlit open-source team definitely does pay attention to the issues (there are 2k+ closed issues, after all), and especially to issues that get lots of s. So, even if it doesnât get addressed right away, having an issue page to discuss a desired feature can be a good place for the community to give feedback about how much they want this new feature, and how they would like to see it work.
I am unable to replicate your issue. The code below displays two tabs and one button in the sidebar. When the button is clicked a function is called and some things in session_state are processed, yet the selected tab doesnât change --for me at least.
Adding more tabs, buttons, processing and state donât seem to make any difference.
def do_stuff():
st.session_state["counter"] += 1
if "counter" not in st.session_state:
st.session_state["counter"] = 0
if st.sidebar.button("Do stuff"):
do_stuff()
tab1, tab2 = st.tabs(["tab1", "tab2"])
tab1.metric("Counter", st.session_state["counter"])
tab2.metric("Squared counter", st.session_state["counter"]**2)
@altanner, did you ever figure this one out? I seem to be having a similar issue. The first interaction on my Streamlit app resets the selected tab to the first one. With subsequent interactions the selected tab is maintained. Running @Goyoâs example on the same environment works without a problem.
Hi all, Today I ran into the same issue. Also for me, running @Goyo 's example works fine. However, I was able to manipulate his example a little bit to let others reproduce the issue. I got inspired by my own use case, where we have a login button for users to authenticate before activating the dashboard.
In order to reproduce the issue, you can run the folllowing code:
import time
import streamlit as st
def do_stuff():
st.session_state["counter"] += 1
if st.sidebar.button("login"):
with st.spinner("please wait"):
time.sleep(3)
st.session_state["user"] = "foo"
if "user" in st.session_state:
if "counter" not in st.session_state:
st.session_state["counter"] = 0
if st.sidebar.button("Do stuff"):
do_stuff()
tab1, tab2 = st.tabs(["tab1", "tab2"])
tab1.metric("Counter", st.session_state["counter"])
tab2.metric("Squared counter", st.session_state["counter"] ** 2)
press the login button
navigate to tab2
click Do stuff
The dashboard goes back to tab1
This happens only once, like @nicomunting says. As of the second time the page remains on the right tab.
How to solve?
I donât have a real satisfying solution, but I noticed the issue is caused by any streamlit widget you pass after the login button. In this example a st.spinner, but it also happens with st.write, st.text, etc⌠If you remove any Streamlit widget, than the issue wonât occur. So, this works:
if st.sidebar.button("login"):
time.sleep(3)
st.session_state["user"] = "foo"
@olafdeleeuw and @Goyo , thanks for the examples. In both cases I get the behaviour that the app switches back to the first tab upon interaction. I guess we should report an issue on GitHub?
I just added a response to the GitHub issue as well. I worked from @olafdeleeuwâs example and simplified it further. Then I saw @Goyoâs simplification above and added another note.
The triggering condition is some difference in frontend state occurring before the tabs are defined. (e.g. having a line that is written conditionally, or using a spinner on some page reruns and not others). As a workaround, try making sure your tabs are defined ahead of any conditional content if you can.
For example, I can modify @Goyoâs example to avoid the error:
import streamlit as st
con = st.container()
tab1, tab2 = st.tabs(["tab1", "tab2"])
if con.button("Click here first"):
con.button("Go to tab2 and click here")
Thanks @mathcatsand. Good to know what triggers this issue exactly. Now I can implement your workaround and define the tabs before the spinner, which in my case triggers the issue, to get rid of the issue. It would be nice of course if this is fixed at some point.