Downloading filtered and sorted data from a reactable in a Shiny app

207 views Asked by At

I'm developing a Shiny app that utilizes the reactable package for tabular data representation. Users can filter and sort columns in the table. I'd like to provide a download button that allows users to download the table data considering the filtering and sorting they may have done.

I am familiar with the rhandsontable package which provides the hot_to_r() function to achieve similar functionality. I'm looking for a parallel solution for reactable.

Below is a basic Shiny app that attempts to provide the desired functionality:

library(shiny)
library(reactable)

ui <- fluidPage(
  downloadButton("downloadData", "Download Data"),
  reactableOutput("my_table")
)

server <- function(input, output, session) {
  
  output$my_table <- renderReactable({
    reactable(head(mtcars), filterable = TRUE)
  })
  
  # Placeholder for downloadHandler
  output$downloadData <- downloadHandler(
    filename = function() {
      paste("data.csv")
    },
    content = function(file) {
      # Attempt to capture and save the current state of the table
      fwrite(as.data.table(head(mtcars)), file)
    },
    contentType = 'text/csv'
  )
}

shinyApp(ui, server)

For instance, I filtered for a speed of 10 and sorted the data by the dist column. How can I download the data displayed in the picture below?

enter image description here

1

There are 1 answers

7
stefan On BEST ANSWER

EDIT

Building on the approach by Victor Perrier we could get the sorted and filtered data via Reactable.getState('my_table').sortedData and pass it to shiny via Shiny.setInputValue. Additionally I had to add an input handler to convert the list into a data.frame:

library(shiny)
library(reactable)

convertToDataFrame <- function(x, session, inputname) {
  do.call("rbind.data.frame", x)
}

registerInputHandler("to_csv", convertToDataFrame, force = TRUE)

ui <- fluidPage(
  downloadButton(
    "downloadData", "Download",
    onClick = "Shiny.setInputValue('table_state:to_csv', Reactable.getState('my_table').sortedData)"
  ),
  reactableOutput("my_table"),
  tableOutput("test")
)

server <- function(input, output) {
  output$my_table <- renderReactable({
    reactable(head(mtcars), filterable = TRUE)
  })
  output$test <- renderTable({
    input$table_state
  })
  output$downloadData <- downloadHandler(
    filename = function() {
      paste("data-", Sys.Date(), ".csv", sep = "")
    },
    content = function(file) {
      data <- input$table_state
      write.csv(data, file)
    }
  )
}

shinyApp(ui, server)

enter image description here

Original Post

Following the example in the docs you can download your filtered and sorted data table by using the reactable download handler for the onclick= event.

library(shiny)
library(reactable)

ui <- fluidPage(
  downloadButton("foo",
    "Download Data",
    onclick = "Reactable.downloadDataCSV('my_table', 'data.csv')"
  ),
  reactableOutput("my_table")
)

server <- function(input, output, session) {
  output$my_table <- renderReactable({
    reactable(head(mtcars), filterable = TRUE)
  })
}

shinyApp(ui, server)

This is the result when filtering for cyl=6 and sorting by mpg:

enter image description here