Ryland Giebelhaus
Ryland Giebelhaus

Reputation: 21

Downloading the outputs of a reactive table in R shiny

I have an R shiny app that gets a .csv import from a user and searches the imported data across a built-in data frame, then gives the % match in the output. The UI is very simple, with a few different inputs (import .csv, a slider, and some radio buttons). What I want is to be able to take the reactive table output and print this to a .csv that the user can download to their machine. The server side of the app looks something like this:

server <- function(input, output){
    rvals <- reactiveValues()

    observeEvent(input$file_1,{
        req(input$file_1)
        rvals$csv <<- read.csv(input$file_1$datapath, header = TRUE)
        #some data processing here
  })

    output$contents <- renderTable({
        if(input$select == 1){
        x <- function
        }else if(input$select == 2){
        x <- function
        }else if(input$select == 3){x <- function}

        #some more data processing and formatting here

        return(x)

    },digits = 4)
}

I would like to have the data table x be able to become a .csv that can be downloaded by clicking a download button. In the server, I added the following code, but when I try to download the data it just downloads a blank file and says "SERVER ERROR" in my downloads manager on my machine.

output$downloadData <- downloadHandler(
    filename = "thename.csv",
    content = function(file){
      write.csv(x, file)
    }

In the console I also get the error message: Warning: Error in is.data.frame: object 'x' not found [No stack trace available]

Upvotes: 0

Views: 1640

Answers (2)

Waldi
Waldi

Reputation: 41260

EventReactive already outputs a reactive value, you don't need to create an extra reactiveVal, see example below :

library(shiny)

# Define UI
ui <- fluidPage(

  # Application title
  titlePanel("Test"),
    mainPanel(
      actionButton("show", "Download"),
      textOutput("result")
    )
  )


server <- function(input, output) {
  csvfile <- eventReactive(req(input$show), ignoreNULL = T, {
      "Content of file"
   })

  output$result <-  reactive(
    paste("result : ",csvfile()))
}

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

I would also avoid to use <<-operator in a reactive expression.

Upvotes: 0

patalt
patalt

Reputation: 475

The object you create inside the expression of renderTable is not available outside of it. Instead you could assign it to the reactive values you set up. Below is a working example (note that I have tried to replicate your code so the data will not be available until you click on "Upload CSV", which here just calls mtcars).

library(shiny)

ui = fluidPage(

  sidebarPanel(
    actionButton(inputId = "uploadCsv", label = "Upload CSV:", icon = icon("upload")),
    selectInput(inputId = "preProc", label = "Pre-processing", choices = c("Mean"=1,"Sum"=2)),
    downloadButton("downloadData", label = "Download table")
  ),

  mainPanel(
    h4("My table:"),
    tableOutput("contents")
  )

)

server <- function(input, output) {

  rvals <- reactiveValues(
    csv=NULL,
    x=NULL
  )

  observeEvent(input$uploadCsv,{
    rvals$csv <- mtcars # using example data since I don't have your .csv
    # rvals$csv <- read.csv(input$file_1$datapath, header = TRUE) 
    #some data processing here
  })

  output$contents <- renderTable({
    # Assuing the below are functions applied to your data
    req(
      input$preProc,
      !is.null(rvals$csv)
    )
    if(input$preProc == 1){
      rvals$x <- data.frame(t(colMeans(mtcars)))
    }else {
      rvals$x <- data.frame(t(colSums(mtcars)))
    }

    return(rvals$x)

  },digits = 4)

  output$downloadData <- downloadHandler(
    filename = "myFile.csv",
    content = function(file){
      write.csv(rvals$x, file)
    }
  )
}

shinyApp(ui,server)

Upvotes: 1

Related Questions