R Shiny:隔离动态选项卡中的动态输出

2023-12-22

我正在尝试创建一个应用程序,您可以在侧边栏中选择某些输入,当您单击按钮时,它将在单独的选项卡中显示结果。我创建了一个小示例,您可以在下面使用。

在此示例中,您在侧栏中选择 4 个字母,如果单击该按钮,它会动态创建一个带有文本输出的单独选项卡。但是,当您更改字母并再次单击该按钮时,所有以前的选项卡都将更新为新结果。我想隔离每个选项卡中的结果,但我不知道该怎么做。我尝试通过使用不同的输出名称来做到这一点(请参阅变量summaryname在服务器中)但它不起作用。

此示例仅使用文本输出,但我的实际应用程序还使用表格和绘图。

我将不胜感激任何帮助!

ui:

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(width = 4,
                 selectInput(inputId = "choice_1", label = "First choice:",
                             choices = LETTERS, selected = "H", multiple = FALSE),
                 selectInput(inputId = "choice_2", label = "Second choice:",
                             choices = LETTERS, selected = "E", multiple = FALSE),
                 selectInput(inputId = "choice_3", label = "Third choice:",
                             choices = LETTERS, selected = "L", multiple = FALSE),
                 selectInput(inputId = "choice_4", label = "Fourth choice:",
                             choices = LETTERS, selected = "P", multiple = FALSE),
                 actionButton(inputId = "goButton", label = "Go!")

    ),
    mainPanel(width = 8,
              tabPanel("Result", fluid = TRUE,
                       uiOutput(outputId = "tabs"),
                       conditionalPanel(condition="input.level == 1",
                                        HTML("<font size = 3><strong>Select your inputs and click 'Go!'.</strong></font>")
                       ),
                       conditionalPanel(condition="input.level != 1",
                                        uiOutput(outputId = "summary")
                       )
              )
    )
  )
)

Server:

server <- function(input, output, session){

  output$tabs <- renderUI({

    Tabs <- as.list(rep(0, input$goButton+1))

    for (i in 0:length(Tabs)){
      Tabs[i] = lapply(paste("Results", i, sep = " "), tabPanel, value = i)
    }

    do.call(tabsetPanel, c(Tabs, id = "level"))
  })

  output$summary <- renderUI({
    summary <- eventReactive(input$goButton, {paste("<strong>", "Summary:", "</strong>", "<br>",
                                                    "You chose the following letters:", input$choice_1, input$choice_2, input$choice_3, input$choice_4, "." ,"<br>",
                                                    "Thank you for helping me!")
    })

    summaryname <- paste("Summary", input$goButton+1, sep = "")

    output[[summaryname]] <- renderText({summary()})
    htmlOutput(summaryname)
  })

}

EDIT:当我尝试在代码周围获取 navbarPage 布局时,我现在遇到了问题。不知何故,动态选项卡的结果显示错误(并且再次未正确隔离)。我只更改了用户界面,但为了以防万一,我添加了服务器。

ui:

ui <- navbarPage("Shiny",

  # Important! : JavaScript functionality to add the Tabs
  tags$head(tags$script(HTML("
                             /* In coherence with the original Shiny way, tab names are created with random numbers. 
                             To avoid duplicate IDs, we collect all generated IDs.  */
                             var hrefCollection = [];

                             Shiny.addCustomMessageHandler('addTabToTabset', function(message){
                             var hrefCodes = [];
                             /* Getting the right tabsetPanel */
                             var tabsetTarget = document.getElementById(message.tabsetName);

                             /* Iterating through all Panel elements */
                             for(var i = 0; i < message.titles.length; i++){
                             /* Creating 6-digit tab ID and check, whether it was already assigned. */
                             do {
                             hrefCodes[i] = Math.floor(Math.random()*100000);
                             } 
                             while(hrefCollection.indexOf(hrefCodes[i]) != -1);
                             hrefCollection = hrefCollection.concat(hrefCodes[i]);

                             /* Creating node in the navigation bar */
                             var navNode = document.createElement('li');
                             var linkNode = document.createElement('a');

                             linkNode.appendChild(document.createTextNode(message.titles[i]));
                             linkNode.setAttribute('data-toggle', 'tab');
                             linkNode.setAttribute('data-value', message.titles[i]);
                             linkNode.setAttribute('href', '#tab-' + hrefCodes[i]);

                             navNode.appendChild(linkNode);
                             tabsetTarget.appendChild(navNode);
                             };

                             /* Move the tabs content to where they are normally stored. Using timeout, because
                             it can take some 20-50 millis until the elements are created. */ 
                             setTimeout(function(){
                             var creationPool = document.getElementById('creationPool').childNodes;
                             var tabContainerTarget = document.getElementsByClassName('tab-content')[0];

                             /* Again iterate through all Panels. */
                             for(var i = 0; i < creationPool.length; i++){
                             var tabContent = creationPool[i];
                             tabContent.setAttribute('id', 'tab-' + hrefCodes[i]);

                             tabContainerTarget.appendChild(tabContent);
                             };
                             }, 100);
                             });
                             "))),
  # End Important

  tabPanel("Statistics"),

  tabPanel("Summary",
    sidebarLayout(
      sidebarPanel(width = 4,
                 selectInput(inputId = "choice_1", label = "First choice:",
                             choices = LETTERS, selected = "H", multiple = FALSE),
                 selectInput(inputId = "choice_2", label = "Second choice:",
                             choices = LETTERS, selected = "E", multiple = FALSE),
                 selectInput(inputId = "choice_3", label = "Third choice:",
                             choices = LETTERS, selected = "L", multiple = FALSE),
                 selectInput(inputId = "choice_4", label = "Fourth choice:",
                             choices = LETTERS, selected = "P", multiple = FALSE),
                 actionButton("goCreate", "Go create a new Tab!")
    ), 
    mainPanel(
      tabsetPanel(id = "mainTabset",
                  tabPanel("InitialPanel1", "Some text here to show this is InitialPanel1",
                           textOutput("creationInfo"),
                           # Important! : 'Freshly baked' tabs first enter here.
                           uiOutput("creationPool", style = "display: none;")
                           # End Important
                  )
      )
    )
    )
  )
)

Server:

server <- function(input, output, session){

  # Important! : creationPool should be hidden to avoid elements flashing before they are moved.
  #              But hidden elements are ignored by shiny, unless this option below is set.
  output$creationPool <- renderUI({})
  outputOptions(output, "creationPool", suspendWhenHidden = FALSE)
  # End Important

  # Important! : This is the make-easy wrapper for adding new tabPanels.
  addTabToTabset <- function(Panels, tabsetName){
    titles <- lapply(Panels, function(Panel){return(Panel$attribs$title)})
    Panels <- lapply(Panels, function(Panel){Panel$attribs$title <- NULL; return(Panel)})

    output$creationPool <- renderUI({Panels})
    session$sendCustomMessage(type = "addTabToTabset", message = list(titles = titles, tabsetName = tabsetName))
  }
  # End Important 

  # From here: Just for demonstration
  output$creationInfo <- renderText({
    paste0("The next tab will be named: Results ", input$goCreate + 1)
  })

  observeEvent(input$goCreate, {
    nr <- input$goCreate

    newTabPanels <- list(
      tabPanel(paste0("NewTab ", nr),

               htmlOutput(paste0("Html_text", nr)),
               actionButton(paste0("Button", nr), "Some new button!"), 
               textOutput(paste0("Text", nr))
      )
    )

    output[[paste0("Html_text", nr)]] <- renderText({
        paste("<strong>", "Summary:", "</strong>", "<br>",
              "You chose the following letters:", isolate(input$choice_1), isolate(input$choice_2), isolate(input$choice_3), isolate(input$choice_4), "." ,"<br>",
              "Thank you for helping me!")
    })

    addTabToTabset(newTabPanels, "mainTabset")
  })
}

修改中给出的代码link https://stackoverflow.com/questions/35020810/dynamically-creating-tabs-with-plots-in-shiny-without-re-creating-existing-tabs/使用您提供的代码,我能够产生所需的结果。

library(shiny)

ui <- shinyUI(fluidPage(

  # Important! : JavaScript functionality to add the Tabs
  tags$head(tags$script(HTML("
                             /* In coherence with the original Shiny way, tab names are created with random numbers. 
                             To avoid duplicate IDs, we collect all generated IDs.  */
                             var hrefCollection = [];

                             Shiny.addCustomMessageHandler('addTabToTabset', function(message){
                             var hrefCodes = [];
                             /* Getting the right tabsetPanel */
                             var tabsetTarget = document.getElementById(message.tabsetName);

                             /* Iterating through all Panel elements */
                             for(var i = 0; i < message.titles.length; i++){
                             /* Creating 6-digit tab ID and check, whether it was already assigned. */
                             do {
                             hrefCodes[i] = Math.floor(Math.random()*100000);
                             } 
                             while(hrefCollection.indexOf(hrefCodes[i]) != -1);
                             hrefCollection = hrefCollection.concat(hrefCodes[i]);

                             /* Creating node in the navigation bar */
                             var navNode = document.createElement('li');
                             var linkNode = document.createElement('a');

                             linkNode.appendChild(document.createTextNode(message.titles[i]));
                             linkNode.setAttribute('data-toggle', 'tab');
                             linkNode.setAttribute('data-value', message.titles[i]);
                             linkNode.setAttribute('href', '#tab-' + hrefCodes[i]);

                             navNode.appendChild(linkNode);
                             tabsetTarget.appendChild(navNode);
                             };

                             /* Move the tabs content to where they are normally stored. Using timeout, because
                             it can take some 20-50 millis until the elements are created. */ 
                             setTimeout(function(){
                             var creationPool = document.getElementById('creationPool').childNodes;
                             var tabContainerTarget = document.getElementsByClassName('tab-content')[0];

                             /* Again iterate through all Panels. */
                             for(var i = 0; i < creationPool.length; i++){
                             var tabContent = creationPool[i];
                             tabContent.setAttribute('id', 'tab-' + hrefCodes[i]);

                             tabContainerTarget.appendChild(tabContent);
                             };
                             }, 100);
                             });
                             "))),
  # End Important
  sidebarLayout(
    sidebarPanel(width = 4,
                 selectInput(inputId = "choice_1", label = "First choice:",
                             choices = LETTERS, selected = "H", multiple = FALSE),
                 selectInput(inputId = "choice_2", label = "Second choice:",
                             choices = LETTERS, selected = "E", multiple = FALSE),
                 selectInput(inputId = "choice_3", label = "Third choice:",
                             choices = LETTERS, selected = "L", multiple = FALSE),
                 selectInput(inputId = "choice_4", label = "Fourth choice:",
                             choices = LETTERS, selected = "P", multiple = FALSE),
                 actionButton(inputId = "goCreate", label = "Go!")

    ),
    mainPanel(width = 8,
  tabsetPanel(id = "mainTabset", 
               tabPanel("InitialPanel1", "Some Text here to show this is InitialPanel1")
  ),

  # Important! : 'Freshly baked' tabs first enter here.
  uiOutput("creationPool", style = "display: none;")
  # End Important
    ))
  ))

server <- function(input, output, session){

  # Important! : creationPool should be hidden to avoid elements flashing before they are moved.
  #              But hidden elements are ignored by shiny, unless this option below is set.
  output$creationPool <- renderUI({})
  outputOptions(output, "creationPool", suspendWhenHidden = FALSE)
  # End Important

  # Important! : This is the make-easy wrapper for adding new tabPanels.
  addTabToTabset <- function(Panels, tabsetName){
    titles <- lapply(Panels, function(Panel){return(Panel$attribs$title)})
    Panels <- lapply(Panels, function(Panel){Panel$attribs$title <- NULL; return(Panel)})

    output$creationPool <- renderUI({Panels})
    session$sendCustomMessage(type = "addTabToTabset", message = list(titles = titles, tabsetName = tabsetName))
  }
  # End Important 

  # From here: Just for demonstration
  output$creationInfo <- renderText({
    paste0("The next tab will be named NewTab", input$goCreate + 1)
  })

  observeEvent(input$goCreate, {
    nr <- input$goCreate
    newTabPanels <- list(
      tabPanel(paste0("Result", nr), 
               # actionButton(paste0("Button", nr), "Some new button!"), 
               htmlOutput(paste0("Text", nr))
      )
    )

    output[[paste0("Text", nr)]] <- renderText({
      paste("<strong>", "Summary:", "</strong>", "<br>",
            "You chose the following letters:", isolate(input$choice_1), isolate(input$choice_2), isolate(input$choice_3), isolate(input$choice_4), "." ,"<br>",
            "Thank you for helping me!")
    })

    addTabToTabset(newTabPanels, "mainTabset")
  })
}

shinyApp(ui, server) 

希望这可以帮助!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

R Shiny:隔离动态选项卡中的动态输出 的相关文章

随机推荐

  • Java 随机种子

    我需要测试一个 Java 程序 20 次 并且需要设置随机种子以便可以重复测试 如果我将初始种子设置为 0 然后在每次运行时递增 1 即 1 2 3 等 即使种子相距不远 此方法是否仍能确保完全随机性 谢谢 任何种子都将提供与标准的任何其他
  • SQL Server:如何导出整个数据库?

    我需要从一台服务器导出数据库并将其导入另一台服务器 如何将整个数据库导出到一个文件或两个文件 mdf ldf 任一选项都可以 如何使用 ssms 将其导入新服务器 小马的指示中写道 在到某个时间点文本框中 要么保留默认值 最近的 可能 或选
  • 原子比较(不等于)和交换

    我想使用原子比较和交换 但我不想等于 而是仅在内存位置不等于旧值时才交换 在C语言中可以吗 这个怎么样 void compare and swap if not equal word t const required non value w
  • 处理事件驱动世界中的异常

    我试图了解如何使用微服务 使用 apache kafka 在事件驱动的世界中处理异常 例如 如果您采用以下订单场景 则需要执行以下操作才能完成订单 1 向支付服务提供商授权支付 2 保留库存商品 3 1 通过支付服务提供商获取支付信息 3
  • 我的 rspec 测试无法通过:Michael Hartl 的 Rails 教程

    我正在第五章末尾做练习 我应该测试链接是否转到正确的页面 这是我的测试代码 require spec helper describe LayoutLinks do it should have the right links on the
  • 为什么无法获取已启动进程的主窗口句柄?

    我遇到过这样的情况 我正在代码中启动一个进程以设置 IPC 通道 我正在启动的进程是一个没有 CLR 支持的 MFC 应用程序 我从中启动此过程的应用程序是 WPF 应用程序中的 C 模块 我认为这对我的问题并不重要 这适用于支持 CLR
  • SIP 软电话客户端的 java SDK

    我想用java构建一个SIP客户端 将向 SIP 注册器注册并能够调用另一个 sip 客户端的 java 类 有什么建议么 如果你愿意的话 你可以尝试我的软件电话 它提供了一个非常简单的API 它被称为同行 http peers sourc
  • 自动映射器映射下拉菜单的 IEnumerable

    Problem 我目前正在将自动映射添加到我的 MVC 项目中 但我陷入了困境 现在我有一个用户模型用于表示数据库中的数据 我必须将该模型映射到 EditUserModel 该模型将在调用 Edit 方法时使用 EditUserModel
  • 尝试调用 Provider.of。这可能是一个错误,因此不受支持

    尝试获取当前用户的 uid 并发送短信 但遇到 Provider 实现错误 尝试致电 Provider of 这可能是一个错误 并且是 因此不受支持 如果你想公开一个变量 可以 任何事情 考虑改变dynamic to Object反而 pa
  • 在 Twig 中将字符串转换为浮点型

    基本上 我设置了一个名为 评级 的参数 它等于一个product DETAILS STAR RATING 它是从数据库驱动字段导入的一个值 该字段恰好是一个字符串 我想将该值乘以 20 但是由于 评级 是一个字符串 我无法将其相乘 如何将字
  • 无法将 Windows 主机目录挂载到 Docker 容器

    我使用的是带有 Docker 版本 1 12 0 rc3 beta18 内部版本 5226 的 Windows 10 Pro 我想在 Windows 机器上使用 Docker 进行 PHP 开发 我尝试了将主机目录安装到 Docker 容器
  • Tensorflow 数据输入切换:训练/验证

    在我从方便但速度较差的占位符切换之后 我的数据通过队列运行器进入我的图表 在每个训练周期之后 我希望运行一次验证 除了训练过程之外 验证过程使用不同的数据 没有增强 也没有洗牌 问题很简单 我如何切换这些东西 一些观察 我无法切换shuff
  • Groovy:带有嵌入引号的字符串未按预期执行

    这很奇怪 使用常规字符串来保存一些要执行的命令行 我发现有时如果字符串中有引号字符 则执行会默默失败 搞什么 已更新 见下文 这是我的测试程序 print 1 grep nameserver etc resolv conf execute
  • Google Speech API v1beta1 很慢?

    当得知 Google 终于为开发者发布了官方语音 API 时 我非常兴奋 我一直对 Google 语音识别在 Android Chrome 和其他产品中的出色表现感到惊讶 我创建了一个 Google Cloud 帐户 启用了语音 API 并
  • 将 X11 窗口保持在另一个窗口之上

    我有两个 x11 窗口 它们需要在彼此之间保持一定的堆叠顺序 即一个窗口需要保持在另一个窗口之上 我不关心应用程序之外的其他窗口 通常 我会为此使用父 子窗口 但由于 X11 将子窗口剪辑到父窗口 所以我必须伪造它 我尝试了各种方法来保留和
  • 在 Python/Pyodbc 中查询 Teradata 时出现问题

    我正在尝试使用 PyODBC 在 Python 中查询 Teradata 数据库 与数据库的连接已建立正常 但是 当我尝试获取结果时 遇到了此错误 十进制文字无效 u 请帮助 我使用的是 RHEL6 Python 2 7 3 这是代码和结果
  • XElement 和列表

    我有一个具有以下属性的类 public class Author public string FirstName get set public string LastName get set 接下来 我有一个作者列表 如下所示 List
  • 对于内容类型建议字符数据的 HTTP 响应,如果未指定,客户端应采用哪种字符集?

    如果 Content Type 标头中未指定字符集参数 RFC2616 第 3 7 1 节 http www w3 org Protocols rfc2616 rfc2616 sec3 html似乎意味着 ISO8859 1 应该被假定为子
  • 有人有“明确定义”的 REST Web 服务的示例吗?

    我阅读了大量有关 REST 与 SOAP 辩论的帖子 问题和答案 我读到一些 REST 支持者声称 精心设计的 REST Web 服务是不言自明的 几乎不需要任何文档 谁能给我指出这样的网络服务吗 最好是有点复杂的 这是一个例子 http
  • R Shiny:隔离动态选项卡中的动态输出

    我正在尝试创建一个应用程序 您可以在侧边栏中选择某些输入 当您单击按钮时 它将在单独的选项卡中显示结果 我创建了一个小示例 您可以在下面使用 在此示例中 您在侧栏中选择 4 个字母 如果单击该按钮 它会动态创建一个带有文本输出的单独选项卡