How to bring the user to a specific tab within a page in my multipage app using the URL?

Summary

I have a multipage app with three tabs - A, B, and C. Lets say within page B I have three tabs X, Y, and Z. I want to bring user to URL/B/Y through the URL. How to do it?

Using “URL/B” the user can directly land on page B. But how to add more parameter to URL to bring user to a custom tab?

1 Like

You could use st.experimental_get_query_params to trigger certain changes on the page layout. For example, if a ?tab=Z is passed to the address, a click on that tab can be triggered to automatically show the contents of that tab.

change_tab_query_param

import streamlit as st

"# Page A"
list_of_tabs = ["X", "Y", "Z"]
tabs = st.tabs(list_of_tabs)

with tabs[0]:
    "## Section X"
    "Some repeated text " * 100

with tabs[1]:
    "## Section Y"
    "Some repeated text " * 100

with tabs[2]:
    "## Section Z"
    "Some repeated text " * 100

# Handling query parameters
query = st.experimental_get_query_params()

try:

    ## Look-up the tab from the query
    index_tab = list_of_tabs.index(query["tab"][0])

    ## Click on that tab
    js = f"""
    <script>
        var tab = window.parent.document.getElementById('tabs-bui2-tab-{index_tab}');
        tab.click();
    </script>
    """

    st.components.v1.html(js)

except ValueError:
    ## Do nothing if the query parameter does not correspond to any of the tabs
    pass

4 Likes

This is fantastic @edsaac
The only change I had to make was in the id of the tab element, It may not be same for different user’s browsers. So I went to inspect element and then found the right element for me.

Without that the code wouldn’t work.

Thank you so much for the help!!

2 Likes

This worked perfectly for me - thanks so much!

            # Define the list of tabs
            list_of_tabs = ["Feed", "Settings", "Files", "Convert", "Dashboard"]

            # Create the tabs
            tabs = st.tabs(list_of_tabs)

            # Handling query parameters
            query = st.experimental_get_query_params()

            try:
                # Look-up the tab from the query
                if "tab" in query:
                    tab_name = query["tab"][0]
                    if tab_name in list_of_tabs:
                        index_tab = list_of_tabs.index(tab_name)
                        
                        # Click on the tab using JavaScript (you may need to change the 'tabs-bui1-tab-' tag)
                        js = f"""
                        <script>
                            var tab = window.parent.document.getElementById('tabs-bui1-tab-{index_tab}');
                            tab.click();
                        </script>
                        """
                        
                        st.components.v1.html(js)
            except ValueError:
                # Do nothing if the query parameter does not correspond to any of the tabs or if "tab" is not present in the query
                pass


           with tabs[0]:
                      st.markdown("Feed")

           with tabs[1]:  
                      st.markdown("Settings")

           with tabs[2]:
                      st.markdown("Files")

Then you can link directly to the tab on the streamlit page using the additional url parameter - eg

/?tab=Settings

The id was “bui3” for me. How reliable has this been over time?

Update: Ok I am going to say this is not reliable. There are some things in the works as can been seen on github regarding this. However you should really be making multipage apps with links instead of tabs when you want to work with url redirection…

Hi, everyone!

I managed to make it work in a similar manner and avoiding the need of setting the “bui_xx” tab group id. However, it will require the “bui” code if you have more than one tab group.

See the code below:

# Generic function to inject js_code
def inject_native_js_code(source: str) -> None:
    div_id = uuid.uuid4()

    components.html(
        f"""
    <div style="display:none" id="{div_id}">
        <script>
            {source}
        </script>
    </div>
    """,
        width=0,
        height=0,
    )

# Specific function to click a given component (matching by id_substring)
def js_click_component(component_id: str):

    source = f"""
            var tab = window.parent.document.querySelector('[id*={component_id}]');
            tab.click();
        """

    inject_native_js_code(source)


# Example call
tab_names = ["Tab_1", "Tab_2"]
tab = st.tabs(tab_names)

st.button(
                   "Switch tab",
                    on_click=utils.js_click_component,
                    kwargs={
                        "component_id": f"tab-{tab_names.index('Tab_2')}",
                    },
                )