Adding Query Parameters to URL on Tab Switch in Streamlit

Hello Streamlit Community,

I’ve been working with Streamlit and utilizing tabs for different sections of my application. I encountered a scenario where I wanted to reflect the tab selection in the URL as query parameters automatically when a user switches tabs. This feature would be incredibly useful for maintaining the state of the app and enhancing user experience by allowing direct links to specific tabs.

Currently, it seems that Streamlit does not support modifying the URL to include query parameters based on tab selection directly and automatically. I was wondering if there’s a straightforward method to achieve this behavior within Streamlit’s current capabilities.

Is there a way to customize or extend Streamlit’s default behavior to add query parameters to the URL upon tab clicks? If not, has there been any discussion or plans to incorporate this feature in future releases? Any guidance or workaround to achieve this functionality would be greatly appreciated.

Thank you for your time and help!

    query_params = st.query_params.to_dict()


    current_tab = query_params.get('tab' , ['1'])[0]
     if current_tab == '1':
            with tab1:
     
                print("tab1tab1tab1tab1tab1tab1")
           
                su_page_module = importlib.import_module("su_page")
                su_page_module.run_sum_main()
               
    
        if current_tab == '2':
            with tab2:
    
                print("tab2tab2tab2tab2tab2tab2")
    
    
                tr_page_module = importlib.import_module("app_trend_main")
    
                tr_page_module.run_trend_main()

Are you coming from another page and want to go to another page’s specific tab?

Tab selection is not available to the python side of your application. You can use radio buttons instead, or some third party widget that looks like tabs but behaves like radio buttons, or create your own.

There is a trick in doing this. If you switch to a specific page with tabs, the opened tab is the tab with index 0. This can be exploited with query params you suggested.

We have home page, page 1. Page 1 has two tabs, data and stats. Now we want to switch directly to stats tab.

image

Creates two url’s with query param.

<li><a href={page1_paths[0]}>Tab data</a></li>
<li><a href={page1_paths[1]}>Tab stats</a></li>

Define page1_paths

base_url = 'http://localhost:8501'
page1_url = f'{base_url}/page1'
target = '_self'
page1_paths = [
    f'"{page1_url}/?tab=data" target="{target}"',
    f'"{page1_url}/?tab=stats" target="{target}"'
]

In page 1 we have the selected tab in front or at index 0, that is the stats tab.

image

If I will go back to home page and select the data tab the result will be this.

image

Now the data tab is in front.

Full code

There are comments in page1 code on how to manipulate the query params and modify the tabs.

home page

import streamlit as st


st.header('Home')

base_url = 'http://localhost:8501'
page1_url = f'{base_url}/page1'
target = '_self'
page1_paths = [
    f'"{page1_url}/?tab=data" target="{target}"',
    f'"{page1_url}/?tab=stats" target="{target}"'
]

po = st.popover(label='Menu')
with po.container(border=False):
    html_str = f'''
    <style>
        a:hover {{
            background-color: yellow;
        }}
    </style>
    <ol type="A">
        <li>Page 1
            <ul>
                <li><a href={page1_paths[0]}>Tab data</a></li>
                <li><a href={page1_paths[1]}>Tab stats</a></li>
            </ul>
        </li>
        <li>Page 2</li>
    </ol>
    '''
    st.markdown(html_str, unsafe_allow_html=True)

page 1

import streamlit as st


st.header('Page 1')

po = st.popover(label='Menu')
with po.container(border=False):
    st.page_link('home.py', label='Home')

# Init dynamic tabs
tabs = ['data', 'stats']

# Get the query parameter with the tab key.
qp = st.query_params.to_dict()
if qp:
    v = qp['tab']

    # Clear the url of the query params as if nothing happens.
    st.query_params.clear()

    # Adjust tabs, put the value of the tab key in front.
    if v in tabs:
        tabs.remove(v)
    tabs.insert(0, v)

# Define tab based on latest tabs.
tab = st.tabs(tabs)

tab[0].subheader(tabs[0])
tab[1].subheader(tabs[1])

.streamlit/config.toml

[client]
showSidebarNavigation = false

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