Search code examples
pythonnavigationshiny-reactivitypy-shiny

How to switch to a certain navigation panel when a button is clicked?


I have an app written in Shiny for Python with several nav panels. On the front page, which the user gets sent to first, I have one button for each other nav panel. Is there any way for me to add functionality so that clicking a button sends you to the appropriate nav panel?

I've found ways to do this in R Shiny, but none in Shiny for Python.

Example code:

from shiny import App, Inputs, Outputs, Session, reactive, render, req, ui
from shiny.express import input, ui

with ui.nav_panel('Start'):
    ui.input_action_button("move_to_panel_1", "Move to panel 1") # clicking this moves you to panel 1  
    ui.input_action_button("move_to_panel_2", "Move to panel 2") # to panel 2

with ui.nav_panel('Panel 1'):
    with ui.card():
        @render.text
        def text1():
            return 'Text 1'

with ui.nav_panel('Panel 2'):
    with ui.card():
        @render.text
        def text2():
            return 'Text 2'


Solution

  • It is possible:

    • Locate the nav_panel()s inside a navigation container. You can choose one of Shiny's ui.navset_* functions, e.g. ui.navset_tab():
      with ui.navset_tab(id="selected_navset_tab"):
          with ui.nav_panel('Start'):
              ...
          with ui.nav_panel(...):
              ...
      
    • Provide a value argument to each of the nav_panel() which you want to make accessible via buttons:
      with ui.nav_panel('Panel 1', value="panel1"):
         ...
      
    • Define an event which is triggered when a button gets clicked, inside it use ui.update_navs() and provide the selected argument with the needed value, e.g.
      @reactive.effect
      @reactive.event(input.move_to_panel_1)
      def _():
          ui.update_navs("selected_navset_tab", selected="panel1")
      

    enter image description here

    from shiny import render, ui, reactive
    from shiny.express import input, ui
    
    with ui.navset_tab(id="selected_navset_tab"):
        with ui.nav_panel('Start'):
            ui.input_action_button("move_to_panel_1", "Move to panel 1") 
            ui.input_action_button("move_to_panel_2", "Move to panel 2")
    
        with ui.nav_panel('Panel 1', value="panel1"):
            with ui.card():
                @render.text
                def text1():
                    return 'Text 1'
    
        with ui.nav_panel('Panel 2', value="panel2"):
            with ui.card():
                @render.text
                def text2():
                    return 'Text 2'
    
    @reactive.effect
    @reactive.event(input.move_to_panel_1)
    def _():
        ui.update_navs("selected_navset_tab", selected="panel1")
    
    @reactive.effect
    @reactive.event(input.move_to_panel_2)
    def _():
        ui.update_navs("selected_navset_tab", selected="panel2")