生成动态数量的数据表而无需重新渲染

时间:2016-10-24 18:35:09

标签: r shiny dt

我想知道处理动态数量的数据表的最佳做法是什么。这是一个玩具示例:

library(shiny)
library(DT)
ui <- shinyUI(fluidPage(
  mainPanel(
    sliderInput("number","Number of tables",1,10,1,1),
    uiOutput("tables")
  )))

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

  observe({
    lapply(seq_len(input$number), function(i) {
      output[[paste0("table",i)]] <- DT::renderDataTable(head(mtcars))
    })
  })

  output$tables <- renderUI({
    lapply(seq_len(input$number), function(i) {
      DT::dataTableOutput(paste0("table",i))
    })
  })


})
# Run the application
shinyApp(ui = ui, server = server)

这种方法是一种生硬的工具,因为无论何时添加或删除单个数据表,都必须重新渲染所有数据表。

是否有更好的方法动态生成输出,不需要在循环中创建所有输出,因此每次更改时都会重新创建所有输出?

2 个答案:

答案 0 :(得分:1)

[编辑]已使用@BárbaraBorges的解决方法更新了答案(有关其工作原理的详细信息,请参阅她的答案)

这是一个示例,但请注意它适用于普通表(无刷新),但对于数据表,删除表时没有刷新,但在添加表时总是刷新。我认为这是由DT引起的,但还没有找到真正的原因。我发帖是希望有人能改进这一点。

library(shiny)
library(DT)

numUI <- 0

ui <- shinyUI(fluidPage(
  mainPanel(
    sliderInput("number","Number of tables",1,10,1,1),
    tags$div(id="tables")
  )))

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

  observe({
    if (input$number > numUI) {
      for (num in (numUI+1):input$number) {
        insertUI("#tables", "beforeBegin", DT::dataTableOutput(paste0("table", num)))
        output[[paste0("table",num)]] <- DT::renderDataTable(head(mtcars), server = FALSE)
      }
    }

    if (input$number < numUI) {
      for (num in (input$number+1):numUI) {
        removeUI(paste0("#table", num))
      }
    }

    numUI <<- input$number
  })

})
# Run the application
shinyApp(ui = ui, server = server)

答案 1 :(得分:1)

我是insertUIremoveUI的作者。在应用于交互式输出时,您似乎在insertUI中发现了一个错误。我提交了一份issue for this in the Shiny repo,并会尽快达成协议。与此同时,解决方法是在where = "beforeBegin"的调用中使用where = "beforeEnd"代替insertUI()。有关详细信息,请参阅DT仓库中提交的原始问题my answer