外部链接到 Shiny App 中的特定 tabPanel

Posted

技术标签:

【中文标题】外部链接到 Shiny App 中的特定 tabPanel【英文标题】:Externally link to specific tabPanel in Shiny App 【发布时间】:2016-01-06 10:16:09 【问题描述】:

在扁平的 Shiny 应用程序中使用锚链接相对容易 - https://***.com/a/28605517/1659890。

但是,外部链接是否可以在 Shiny 应用中针对特定的 tabPanelnavbarPage

考虑以下测试应用: 用户界面:

shinyUI(navbarPage(
  "Anchor Test",
  tabPanel(
    "Panel 1", fluidPage(html(
      paste(
        "<p>I'm the first panel</p>","<p><a href='#irisPlotUI'>Link to irisPlotUI in panel 2</a></p>",
        "<a href='#panel2'>Link to panel 2</a>",sep = ""
      )
    ))
  ),
  tabPanel("Panel 2", fluidPage(
    "I'm the second panel", uiOutput("irisPlotUI")
  ),
  value = "#panel2"),
  tabPanel("Panel 3", "I'm a table!!!")

服务器:

shinyServer(function(input, output) 
  output$irisPlotUI <- renderUI(plotOutput("irisPlot"))
  output$irisPlot <- renderPlot(plot(iris$Sepal.Length))
  )

使用链接答案中的方法不起作用,irisPlotUI 的 id 是正确的,但它是情节所在的 tabPanel 的孩子。

tabPanel 中的data-value 通过使用参数value 被赋予"panel2" 的值,但是Shiny 应用程序继续为tabPanel 提供一个我不知道的唯一ID如何定位。

我检查了已部署的 Shiny 应用程序的来源,例如 https://martinjhnhadley.shinyapps.io/AnchorLinks,并找到了指向 tabPanel 的实际链接:https://internal.shinyapps.io/martinjhnhadley/AnchorLinks/?initialWidth=1074&childId=shinyapp#tab-8850-2

但是,直接导航到此链接也不会将我定向到选项卡。

锚链接是我定位应用程序部分的唯一选择,还是有一个 Shiny 特定的解决方案?

如果不是,我如何插入一个脚本,例如此处显示的https://***.com/a/15637801/1659890,以允许在登陆 Shiny 应用程序时执行 javascript,以与此 https://groups.google.com/d/msg/shiny-discuss/sJlasQf71fY/RW7Xc8F02IoJ 类似的方式选择 tabPanel

感谢 daattali 的解决方案

使用 daattali 的回答,我还可以从他那里找到以下内容 - https://github.com/rstudio/shiny/issues/772#issuecomment-112919149

以下内容完全符合我的需求,请注意,我选择遵守他使用的/?url= 约定:

UI.R

shinyUI(
  navbarPage( "test", id = 'someID',
              tabPanel("tab1", h1("page1")),

              navbarMenu( "menu",
                          tabPanel('tab2a',  value='nested1', h1("page2a")),
                          tabPanel('tab2b',  value='nested2', h1("page2b")),
                          tabPanel('tab_sub',  "foobar")
              ),
              tabPanel("tab3", h1("page3"))
  ))

服务器.R

url1 <- url2 <- ""

shinyServer(function(input, output, session) 

  values <- reactiveValues(myurl = c(), parent_tab = "")

  observe(
    # make sure this is called on pageload (to look at the query string)
    # and whenever any tab is successfully changed.
    # If you want to stop running this code after the initial load was
    # successful so that further manual tab changes don't run this,
    # maybe just have some boolean flag for that.

    input$someID
    input$tab_sub_tabs
    query <- parseQueryString(session$clientData$url_search)
    url <- query$url
    if (is.null(url)) 
      url <- ""
    

    # "depth" is how many levels the url in the query string is
    depth <- function(x) length(unlist(strsplit(x,"/")))

    # if we reached the end, done!
    if (length(values$myurl) == depth(url)) 
      return()
    
    # base case - need to tell it what the first main nav name is
    else if (length(values$myurl) == 0) 
      values$parent_tab <- "someID"
    
    # if we're waiting for a tab switch but the UI hasn't updated yet
    else if (is.null(input[[values$parent_tab]])) 
      return()
    
    # same - waiting for a tab switch
    else if (tail(values$myurl, 1) != input[[values$parent_tab]]) 
      return()
    
    # the UI is on the tab that we last switched to, and there are more
    # tabs to switch inside the current tab
    # make sure the tabs follow the naming scheme
    else 
      values$parent_tab <- paste0(tail(values$myurl, 1), "_tabs")
    

    # figure out the id/value of the next tab
    new_tab <- unlist(strsplit(url, "/"))[length(values$myurl)+1]

    # easy peasy.
    updateTabsetPanel(session, values$parent_tab, new_tab)
    values$myurl <- c(values$myurl, new_tab)
  )
)

【问题讨论】:

我忘记了我写的那段代码 :) 我认为这段代码对于你的需要来说过于复杂了,除非你有很多选项卡并且每个选项卡都可以有嵌套的选项卡并且你不提前知道选项卡的名称。我写的那个解决方案是专门针对这种一般情况的。在您的情况下,如果您只有一级选项卡(与嵌套选项卡相比),那么大部分代码都是不必要的 @daattali 啊,好吧,对于这个最小的工作示例来说确实如此,但真正闪亮的应用程序有很多级别。不过好暴力。我个人认为这是其他人会从中受益并且很难找到的东西,值得写博客吗? 我计划很快写一篇关于许多不同的中级到高级闪亮技术的博客,其中将包括我经常看到的许多常见问题以及用于解决这些问题的代码的 sn-ps 以及解释。我已经有这个了:) 【参考方案1】:

我发现另一个答案有点难以理解,所以我创建了下面的示例。要导航到“数据可用性”选项卡,请将“?a=b”放在 URL 的末尾。例如,如果在端口 7436 上托管应用程序,则以下链接将直接将您带到数据可用性页面。 http://127.0.0.1:7436/?a=b

library(shinydashboard)
library(shiny)
ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(
    sidebarMenu(id = "container",
      menuItem("Channels", tabName = "lt_channels"),
      menuItem("Data Availability", tabName = "data_avail")
    )),
  dashboardBody(
    tabItems(
      tabItem(tabName = "lt_channels",
              h1("Test Fail")),
      tabItem(tabName = "data_avail",
              h1("Test Pass"))
    )
  )
)



server <- function(session, input, output)
  observe(
    query <- parseQueryString(session$clientData$url_search)
    query1 <- paste(names(query), query, sep = "=", collapse=", ")
    print(query1)
    if(query1 == "a=b")
      updateTabItems(session, inputId = "container", selected = "data_avail")
    
  )

shinyApp(ui = ui, server = server)

【讨论】:

【参考方案2】:

您可以将搜索查询参数添加到 URL(例如 href='www.myapp.com?tab=tab2),并且在被链接的应用程序中,您必须添加一些逻辑,如果搜索字符串在初始化时更改为指定选项卡存在(例如,查看session$clientData$url_search,如果它存在并且有一个tab 变量,则使用updateTabsetPanel() 转到该选项卡)

【讨论】:

非常感谢 - 原来我之前已经提到了很多内容,很高兴能够说声谢谢:)

以上是关于外部链接到 Shiny App 中的特定 tabPanel的主要内容,如果未能解决你的问题,请参考以下文章

R shiny 中的级别替换创建两个级别列表,一个为 NULL

03.Python Dash网页开发:多页面网站制作

如何在 R Shiny App 中保留复选框中的值?

通过导航到 navbarPage 中的特定 tabPanel 触发 R Shiny 反应式

R shiny教程-3:添加小部件到Shiny App

如何在Shiny app中的仪表板主体中输出数据库表?