Extract filters from R Shiny Datatable

廉价感情. 提交于 2019-12-21 04:39:25

问题


I have a DT data table in R Shiny and I have enabled column filtering by setting filter="top" within renderDT(). I now want to extract the user-applied filters so I can save them in variables server-side and reapply them when -- for instance -- a database is updated, requiring an update of the table.

Here's a MWE using Shiny Dashboard:

library(shiny)           #  Shiny web app
library(shinydashboard)  #  Dashboard framework for Shiny
library(plotly)          #  Plotly interactive plots
library(DT)

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    fluidRow(column(12, DTOutput("table")))
  )
)

server <- function(input, output, session) {
  fileData <- reactiveFileReader(1000, session, 'test.csv', read.csv)
  output$table <- renderDT(fileData(), filter = "top")
}

shinyApp(ui, server)

To reiterate, I'd like to save the filters (for instance, a user might select a range of numeric values or a specific factor from one of the filter boxes) as input$ variables so I can use them on the server side.


回答1:


I think the simplest way to do this is to just add

options = list(stateSave = TRUE)

inside the renderDT() function. Then, within the server, the state of the table can be accessed at any time with input$<tableID>_state (my table is just called "table" so this becomes input$table_state:

observeEvent(input$table_state, {
  str(input$table_state)
})

The whole solution is then:

library(shiny)
library(shinydashboard)
library(plotly)
library(DT)

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    box(DTOutput("table"))
  )
)

server <- function(input, output, session) {
  fileData <- reactiveFileReader(1000, session, 'www/test.csv', read.csv)
  output$table <- renderDT(fileData(), filter = "top",
    options = list(stateSave = TRUE))

  observeEvent(input$table_state, {
    str(input$table_state)
  })

}

shinyApp(ui, server)

Sample output within the RStudio console:

List of 6
 $ time   : num 1.54e+12
 $ start  : int 0
 $ length : int 10
 $ order  : list()
 $ search :List of 4
  ..$ search         : chr ""
  ..$ smart          : logi TRUE
  ..$ regex          : logi FALSE
  ..$ caseInsensitive: logi TRUE
 $ columns:List of 5
  ..$ :List of 2
  .. ..$ visible: logi TRUE
  .. ..$ search :List of 4
  .. .. ..$ search         : chr ""
  .. .. ..$ smart          : logi TRUE
  .. .. ..$ regex          : logi FALSE
  .. .. ..$ caseInsensitive: logi TRUE
  ..$ :List of 2
  .. ..$ visible: logi TRUE
  .. ..$ search :List of 4
  .. .. ..$ search         : chr "[\"0\"]"
  .. .. ..$ smart          : logi TRUE
  .. .. ..$ regex          : logi FALSE
  .. .. ..$ caseInsensitive: logi TRUE
  ..$ :List of 2
  .. ..$ visible: logi TRUE
  .. ..$ search :List of 4
  .. .. ..$ search         : chr "[\"8\"]"
  .. .. ..$ smart          : logi TRUE
  .. .. ..$ regex          : logi FALSE
  .. .. ..$ caseInsensitive: logi TRUE
  ..$ :List of 2
  .. ..$ visible: logi TRUE
  .. ..$ search :List of 4
  .. .. ..$ search         : chr ""
  .. .. ..$ smart          : logi TRUE
  .. .. ..$ regex          : logi FALSE
  .. .. ..$ caseInsensitive: logi TRUE
  ..$ :List of 2
  .. ..$ visible: logi TRUE
  .. ..$ search :List of 4
  .. .. ..$ search         : chr ""
  .. .. ..$ smart          : logi TRUE
  .. .. ..$ regex          : logi FALSE
  .. .. ..$ caseInsensitive: logi TRUE

Note the search lists which show the filters applied to each column.

Bonus

For super-easy filter extraction, use input$table_search_columns. This gives the same result as using sapply:

sapply(input$table_state$columns, function(x) x$search$search)

This will give something like

[1] ""        "[\"0\"]" "[\"8\"]" ""        ""      

for the above example.




回答2:


There may be a simpler way to do this, but here's my quick 5 minute solution:

Every time the table redraws (which will happen when you update a filter, but will also happen when you sort, paginate, or do anything else that causes a redraw), inject some javascript that looks for the value of the filter you're interested in. We can use then use this method to send the value as an input to the server side of the shiny app in R.

I will be using the mtcars dataset rather than a csv file, I'm using a slightly simpler template than what you provided, and I'll be specifically looking for filtered values of the third column which is disp. This should be enough to help you solve your specific case.

library(shiny)

ui <- fluidPage(
  "disp filter:",
  textOutput("dispOut"),
  DT::dataTableOutput("table")
)

server <- function(input, output, session) {
  output$table <- DT::renderDataTable(
    DT::datatable(
      mtcars,
      filter = "top",
      options = list(
        drawCallback = JS('function(){ Shiny.onInputChange("dispFilter", this.api().table().columns(3).search()[0]); }')
      )
    )
  )

  output$dispOut <- renderText(input$dispFilter)
}

shinyApp(ui,server)

Edit: the other answer by @awwsmm is better, this one is more javascript based, the other is more shiny



来源:https://stackoverflow.com/questions/52858889/extract-filters-from-r-shiny-datatable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!