22

How do I manage to link from a given shiny part to parts that are located on other tabs/panels?

Update

The solution I drafted below works for the explicit case of linking to tabs/panels (and that's what I asked for).

However, I'd be interested to also know about more generic ways of linking parts of a shiny app.

Example

I'd like to link from panel A to panel B, but I'm not quite sure what I need to specify as an action when the action link in panel A is clicked.

The value #tab-4527-2 came from investigating the HTML output of ui, but I just saw that those values change each time I restart the app.

library(shiny)

# UI ---------------------------------------------------------------------

ui <- fluidPage(
  tabsetPanel(
    tabPanel(
      "A",
      p(),
      actionLink("link_to_tabpanel_b", "Link to panel B")
    ),
    tabPanel(
      "B",
      h3("Some information"),
      tags$li("Item 1"),
      tags$li("Item 2")
    )
  )
)

# Server ------------------------------------------------------------------

server <- function(input, output, session) {
  observeEvent(input$link_to_tabpanel_b, {
    tags$a(href = "#tab-4527-2")
  })
}

shinyApp(ui, server)
Rappster
  • 12,762
  • 7
  • 71
  • 120
  • 1
    Would this help http://stackoverflow.com/questions/32971921/navigate-to-particular-sidebar-menu-item-in-shinydashboard/32972517#32972517 – Pork Chop Dec 16 '15 at 15:41
  • @PorkChop: it does solve my immediate problem, thanks! Do you know of a more generic way to link arbitrary shiny app parts? – Rappster Dec 16 '15 at 15:54
  • 1
    All the `HTML` components will have a `unique` ID assigned to them, so you can use those to link yout things together. If you want to do something complex you would need to write a bit of `Javascript`. You can have a look at example [here] https://groups.google.com/forum/#!topic/shiny-discuss/sJlasQf71fY – Pork Chop Dec 16 '15 at 16:02
  • I found by replacing updateTabItems() with updateTabsetPanel() you can forgo do this with only the Shiny library and you don't need to load shinydashboard. Not a big deal. – SprengMeister Dec 16 '15 at 16:26
  • @SprengMeister: thanks, good to know that – Rappster Dec 16 '15 at 16:45

5 Answers5

13

The following solution is based on the inputs I got from the comments.

Note that updateTabsetPanel() belongs to shiny while updateTabItems() is a function of the shinydashboard package. They seem to work interchangeably.

library(shiny)
library(shinydashboard)

# UI ---------------------------------------------------------------------

ui <- fluidPage(
  tabsetPanel(
    id = "panels",
    tabPanel(
      "A",
      p(),
      actionLink("link_to_tabpanel_b", "Link to panel B")
    ),
    tabPanel(
      "B",
      h3("Some information"),
      tags$li("Item 1"),
      tags$li("Item 2"),
      actionLink("link_to_tabpanel_a", "Link to panel A")
    )
  )
)

# Server ------------------------------------------------------------------

server <- function(input, output, session) {
#   observeEvent(input$link_to_tabpanel_b, {
#     tags$a(href = "#tab-4527-2")
#   })
  observeEvent(input$link_to_tabpanel_b, {
    newvalue <- "B"
    updateTabItems(session, "panels", newvalue)
  })
  observeEvent(input$link_to_tabpanel_a, {
    newvalue <- "A"
    updateTabsetPanel(session, "panels", newvalue)
  })
}

shinyApp(ui, server)
Rappster
  • 12,762
  • 7
  • 71
  • 120
5

We have just released a routing library, which makes linking in Shiny easy. Here's how it looks like in a nutshell.

make_router(
   route("<your_app_url>/main",  main_page_shiny_ui),
   route("<your_app_url>/other", other_page_shiny_ui)
)

More information can be found in this blog post.

  • 1
    We had to change a package name to "shiny.router". I've just changed the links in blog post. So @Rappster if you are using our library already please make sure to update your GIT configs. – KrzysztofWrobel Dec 13 '16 at 12:56
5

You can give your tabsetPanel an id and use updateTabsetPanel with your observeEvent

library(shiny)

# UI ---------------------------------------------------------------------

ui <- fluidPage(
  tabsetPanel(id = "demo",
    tabPanel(
      "A",
      p(),
      actionLink("link_to_tabpanel_b", "Link to panel B")
    ),
    tabPanel(
      "B",
      h3("Some information"),
      tags$li("Item 1"),
      tags$li("Item 2")
    )
  )
)

# Server ------------------------------------------------------------------

server <- function(input, output, session) {
  observeEvent(input$link_to_tabpanel_b, {
    updateTabsetPanel(session, "demo", "B")
  })
}

shinyApp(ui, server)
thesadie
  • 51
  • 1
  • 3
4

I was struggling with the same issue and really wanted to link to a different tab via the URL. Thanks to the simple example of thesadie and by using an observe to parse inputs from the url, for me the following worked (and made it possible to switch the tab by adding /?tab=B to the URL, e.g. http://localhost:1234/?tab=B):

library(shiny)

# UI ---------------------------------------------------------------------

ui <- fluidPage(
  tabsetPanel(id = "demo",
              tabPanel(
                "A",
                p(),
                actionLink("link_to_tabpanel_b", "Link to panel B")
              ),
              tabPanel(
                "B",
                h3("Some information"),
                tags$li("Item 1"),
                tags$li("Item 2")
              )
  )
)

# Server ------------------------------------------------------------------

server <- function(input, output, session) {
  # Allow url parsing
  observe({
    query <- parseQueryString(session$clientData$url_search)
    if (!is.null(query)) {
      for (name in names(query)) {
        if (name == "tab") {
          # Change tab
          try(updateTabsetPanel(session, "demo", selected = query[[name]]))
        } else {
          # Update inputs - this part is not really necessary if you just want to change the tabs, 
          # but I also needed to update other inputs from the url
          try(updateTextInput(session, name, value = query[[name]]), silent = TRUE)
        }
      }
    } 
  })
  
  observeEvent(input$link_to_tabpanel_b, {
    updateTabsetPanel(session, "demo", "B")
  })
}

shinyApp(ui, server)
eh21
  • 629
  • 7
  • 7
0

According to the code and logic from Rappster. It is possible to set any kind of links. Link to TabsetPanel can be used by updataTabsetPanel. Link to Navbar can use updateNavbarPage(session, inputId, selected = NULL). These can be found by ?updateTabsetPanel as following.

updateTabsetPanel(session, inputId, selected = NULL)

updateNavbarPage(session, inputId, selected = NULL)

updateNavlistPanel(session, inputId, selected = NULL)

Please notice selected is the new id that you can define for tabsetPanel, Navbar, or NavlistPanel.

Xiaorui Zhu
  • 161
  • 7