Shiny - renderDataTable - bSearchable vs checkboxInput

时间:2014-08-15 20:01:34

标签: r datatables shiny

在构建数据表时,我在组合两个功能时遇到了问题:

  1. 我使用“bSearchable”选择我想使用搜索工具过滤的1列
  2. 我使用“checkboxInput”选择用户想要查看的列。
  3. 两者分开工作,但不能一起工作。如果我取消选中菜单输入中的列,数据就会消失 - 就像应用过滤器一样,没有找到数据。我该如何解决这个问题?

              library(shiny)    
    runApp(list(ui=(fluidPage(
          pageWithSidebar(
            headerPanel('Title'),
            sidebarPanel(
              helpText('Text about the table'),
    
              checkboxInput('columns','I want to select the columns' , value = FALSE),
    
              conditionalPanel(
                condition= "input.columns == true",
                checkboxGroupInput('show_vars', 'Select the columns that you want to see:', names(iris[1:4]),
                                   selected =  names(iris[1:4]))
              ),
    
              downloadButton('downloadData', 'Download'),width = 3
    
            ),
            mainPanel(
              tags$head(tags$style("tfoot {display: table-header-group;}")),
              dataTableOutput("mytable1"),width = 9
    
            )
          ))
        )
    
        ,
    
        server=(function(input, output) {
    
          library(ggplot2) 
          library(XLConnect)  
    
          #DATA 
          tabel<- reactive({
            iris[,c(input$show_vars,"Species"), drop = FALSE]
    
          })
    
          #   OUTPUT   
          output$mytable1 = renderDataTable({
            tabel()}, 
            options = list(    
              aoColumns = list(list(bSearchable = FALSE), list(bSearchable = FALSE),list(bSearchable = FALSE),
                               list(bSearchable = FALSE),list(bSearchable = TRUE)),
              bFilter=1, bSortClasses = 1,aLengthMenu = list(c(10,25,50, -1), list('10','25', '50', 'Todas')),iDisplayLength = 10
            )
    
          )
    
          output$downloadData <- downloadHandler(
            filename = function() { paste('tabela_PSU','.xlsx', sep='') },
            content = function(file){
              fname <- paste(file,"xlsx",sep=".")
              wb <- loadWorkbook(fname, create = TRUE)
              createSheet(wb, name = "Sheet1")
              writeWorksheet(wb, tabel(), sheet = "Sheet1") 
              saveWorkbook(wb)
              file.rename(fname,file)
            },
          )
    
    
        })
        ))
    

1 个答案:

答案 0 :(得分:2)

问题在于根据iris过滤数据input$show_vars,您正在更改DataTable的列数。 但是,您已经定义了固定 aoColumns选项,这意味着您的DataTable有五列(四个不可搜索,一个可搜索)。

因此,当您取消选择任何复选框输入时,过滤后的数据与指定的选项不匹配。结果,没有显示任何内容。

也就是说,虽然DataTable中的数据是被动,但选项无反应

如果仔细阅读renderDataTable's document,您会发现可以将两种类型的变量传递给options参数:

  

options要传递给DataTables的初始化选项列表,或返回此类列表的函数。

区别在于:

  • 如果您将options指定为列表,则Shiny会假定options已修复;但是,由于您是基于input$show_vars动态过滤数据,因此动态更改aoColumns的选项。
  • 如果您将函数作为options的参数传递,Shiny将知道options也是被动的。因此,当数据(在您的情况下,options封装在名为data.frame的反应变量中)更新时,Shiny也会更新tabel

您可能已经知道反应变量本身就是功能。它们在被动环境中进行评估,在评估时,它们返回数据的当前状态/值。这就是您将tabel()而不是tabel传递给renderDataTable的原因。

然后,解决方案是将整个options列表包装成一个反应变量(因此也是一个函数)。具体来说,我们想要动态设置aoColumns选项,以便bSearchable切换的数量与DataTable中显示的列数相匹配。

下面我只显示更新的server部分,因为在UI部分中无需更改任何内容。

server.R

shinyServer(function(input, output) {

  library(ggplot2) 
  library(XLConnect)  

  #DATA 
  tabel<- reactive({
    iris[,c(input$show_vars,"Species"), drop = FALSE]

  })

  # wrap the `options` into a reactive variable (hence a function) so that it will
  # be evaluated dynamically when the data changes as well. 
  # `dt_options` is reactive in the sense that it will reflect the number of rows
  # visible based on the checkboxInput selections.

  dt_options <- reactive({
    # dynamically create options for `aoColumns` depending on how many columns are selected.
    toggles <- lapply(1:length(input$show_vars), function(x) list(bSearchable = F))
    # for `species` columns
    toggles[[length(toggles) + 1]] <- list(bSearchable = T)

    list(
      aoColumns = toggles,
      bFilter = 1, bSortClasses = 1, 
      aLengthMenu = list(c(10,25,50, -1), list('10','25', '50', 'Todas')),
      iDisplayLength = 10
      )
  })

  #   OUTPUT
  output$mytable1 = renderDataTable({
    tabel()}, 
    options = dt_options
  )

  output$downloadData <- downloadHandler(
    filename = function() { paste('tabela_PSU','.xlsx', sep='') },
    content = function(file){
      fname <- paste(file,"xlsx",sep=".")
      wb <- loadWorkbook(fname, create = TRUE)
      createSheet(wb, name = "Sheet1")
      writeWorksheet(wb, tabel(), sheet = "Sheet1") 
      saveWorkbook(wb)
      file.rename(fname,file)
    },
  )

})

(请注意,我将UI部分和服务器部分分为ui.Rserver.R。)