简体   繁体   English

闪亮-renderDataTable-bSearchable vs checkboxInput

[英]Shiny - renderDataTable - bSearchable vs checkboxInput

I´m having problems combining two features while building a data table: 建立数据表时,我在合并两个功能时遇到问题:

  1. I use “bSearchable” to select 1 column that I want to use the search tool to filter 我使用“ bSearchable”选择要使用搜索工具进行过滤的1列
  2. I use "checkboxInput" to select the columns the user wants to see. 我使用“ checkboxInput”来选择用户想要查看的列。

Both work separately, but not together. 两者都是分开工作的,但不能一起工作。 If I uncheck a column in my menu input, the data disappears - like applying a filter and no data was found. 如果取消选中菜单输入中的一列,数据将消失-就像应用过滤器一样,未找到任何数据。 How can I fix this? 我怎样才能解决这个问题?

          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)
        },
      )


    })
    ))

The problem is by filtering the data iris based on input$show_vars , you are changing the number of columns of the DataTable. 问题是通过更改基于input$show_vars的数据iris ,您正在更改DataTable的列数。 However, you have defined a fixed aoColumns option, which implies your DataTable has five columns (four non-searchable, one searchable). 但是,您已经定义了一个固定的 aoColumns选项,这意味着您的DataTable具有五列(四列不可搜索,一列可搜索)。

Therefore, when you deselect any checkbox inputs, the filtered data doesn't match the specified options. 因此,当取消选择任何复选框输入时,过滤的数据与指定的选项不匹配。 As a result, nothing is displayed. 结果,什么也不显示。

That is, although your data in the DataTable is reactive , the options, however, are NOT reactive . 也就是说,尽管您在DataTable中的数据是反应性的,但是选项不是反应性的

If you read the renderDataTable 's document carefully, you will see that you can pass two types of variables to the options argument: 如果您仔细阅读renderDataTable的文档 ,将会看到可以将两种类型的变量传递给options参数:

options A list of initialization options to be passed to DataTables, or a function to return such a list. options传递给DataTables的初始化选项的列表,或者返回该列表的函数。

The differences are: 不同之处在于:

  • If you specify options as a list, Shiny assumes that the options are fixed; 如果您将options指定为列表,Shiny会假定options是固定的; But since you are dynamically filtering the data based on input$show_vars , you should dynamically change the options for aoColumns as well. 但是,由于要基于input$show_vars动态过滤数据,因此也应该动态更改aoColumns的选项。
  • If you pass a function as an argument for options , Shiny will know that the options are also reactive. 如果将函数作为options的参数传递,Shiny将知道这些options也是反应性的。 Hence Shiny will also update the options when the data (in your case, the data.frame encapsulated in the reactive variable named tabel ) updates. 因此闪亮还将更新options时的数据(在你的情况下, data.frame中的反应变量命名封装tabel更新)。

You may already know that reactive variables are themselves functions . 您可能已经知道, 反应变量本身就是函数 They are evaluated in a reactive environment and when evaluated, they return the current state/value of the data. 在反应性环境中对它们进行评估,并在评估时返回数据的当前状态/值。 This is why you pass tabel() instead of tabel to renderDataTable . 这就是为什么您将tabel()而不是tabelrenderDataTable

The solution then, is to wrap the entire options list into a reactive variable (hence a function as well). 然后,解决方案是将整个options列表包装到一个反应变量中(因此也有一个函数)。 Specifically, we want to dynmaically set the aoColumns option so that the number of bSearchable toggles matches the number of columns shown in the DataTable. 具体来说,我们要动态设置aoColumns选项,以便bSearchable切换次数与DataTable中显示的列数匹配。

Below I only show the updated server part, since there's nothing needs to be changed in the UI part. 下面,我仅显示更新的server部分,因为在UI部分中无需更改任何内容。

server.R 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)
    },
  )

})

(Note that I separate the UI part and server part into ui.R and server.R .) (请注意,我将UI部分和服务器部分分为ui.Rserver.R 。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM