1

I have a shiny app that creates a data frame based on user inputs. I want to make a dynamic download button that takes user choices (radioButton) to download dynamically made data frame. The data frames are returned from a function as a list

When I create functions for two different download buttons the downloading works fine

library(shiny)
library(DT)

temp_func <- function(){
  x <- mtcars
  y = x[,1]
  return(list(complete_df = as.data.frame(x), column1 = as.data.frame(y)))
}

# UI
ui <- shinyUI({
  fluidPage(
    actionButton("fetch", label = "Fetch data first"),
    
    mainPanel(DT::dataTableOutput("table")),
    
    downloadButton("down_all", "Download all"),
    downloadButton("down_c1", "Download c1")
    
)})

# Server
server <- Main_Server <- function(input,output,session){
  
  # Reactive Values
  values <- reactiveValues(table = NULL)
  
  # fetchEvent (Consider temp_func() is fetching data from website)
  observeEvent(input$fetch, {values$table <- temp_func()})
  
  # Rendering table for display
  output$table <- renderDT({datatable(values$table$complete_df)})
  
  # Download 1
  output$down_all <- downloadHandler(
    filename = function() { paste("All columns","csv", sep=".")},
    content = function(file) {write.csv(values$table$complete_df, file)})
  
  # Download 2
  output$down_c1 <- downloadHandler(
    filename = function() { paste("Columns1","csv", sep=".")},
    content = function(file) {write.csv(values$table$column1, file)})
}

# Run-app
shinyApp(ui, server)

Once I merge the two functions and pass input$choice from radio button I get an empty file

library(shiny)
library(DT)

temp_func <- function(){
  x <- mtcars
  y = x[,1]
  return(list(complete_df = as.data.frame(x), column1 = as.data.frame(y)))
}

# UI
ui <- shinyUI({
  fluidPage(
    actionButton("fetch", label = "Fetch data first"),
    
    mainPanel(DT::dataTableOutput("table")),
    
    radioButtons("rd", c("Select"), choices = c("All Columns" = "complete_df","Column 1" = "column1"),
                 selected = "complete_df"),
    downloadButton("down", "Download")
    
  )})

# Server
server <- Main_Server <- function(input,output,session){
  
  # Reactive Values
  values <- reactiveValues(table = NULL)
  
  # fetchEvent (Consider temp_func() is fetching data from website)
  observeEvent(input$fetch, {values$table <- temp_func()})
  
  # Rendering table for display
  output$table <- renderDT({datatable(values$table$complete_df)})
  
  # Combined Download
  output$down <- downloadHandler(
    filename = function() { paste("File","csv", sep=".")},
    content = function(file) {write.csv(values$table$input$rd, file)})
  
}

# Run-app
shinyApp(ui, server)

Consider temp_func() is fetching data from other website

sp29
  • 363
  • 4
  • 11
  • Can you please make a complete [minimal reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example). Either further adapt the example code to your problem or provide the UI and needed Data for `Main_Server`. Thanks! – starja Jul 19 '20 at 08:28
  • I have added reproducible code – sp29 Jul 19 '20 at 09:17
  • 1
    Thanks. @Waldi's answer does the trick, try `values$table[[input$rd]]` instead of `values$table$input$rd` – starja Jul 19 '20 at 09:34

1 Answers1

4

Try to use :

 # Combined Download
  output$down <- downloadHandler(
    filename = function() { paste("File","csv", sep=".")},
    content = function(file) {write.csv(values$table[[input$rd]], file)})

The syntax you used returns NULL because values$table doesn't have an input field.
With the updated syntax, the downloaded file isn't empty anymore.

Waldi
  • 39,242
  • 6
  • 30
  • 78