Home > database >  How to write a file based on eventReactive
How to write a file based on eventReactive

Time:05-30

My app allows the user to generate some plots and save them as png.

I want the app as well to update a csv file based on some inputs made into the app by the user.

For example purposes, I created a toy app that generates a csv file in a given folder.

In both cases, the app doesn't display any error message or info, but it doesn't store any file anywhere.

library(shiny)
library(ggplot2)
library(AlphaPart)

ui <- fluidPage(
  selectInput("var1","Select var1", choices = names(iris)),
  selectInput("var2","Select var2", choices = names(iris)),
  plotOutput("myplot"),
  downloadLink("downloadPlot", label = icon("download")))

server <- function(input, output, session) {
  
  data <- reactive(iris)
  var1 <- reactive({input$var1})
  var2 <- reactive({input$var2})
  
  # Genearte plot
  draw_boxplot <- function(data, var1, var2){
    ggplot(data=data(), aes(x=.data[[input$var1]], y = .data[[input$var2]])) 
      geom_boxplot() 
  }
  
  plot1 <- reactive({
    req(data(), input$var1, input$var2)
    draw_boxplot(data(), var1(), var2())
  })
  
  output$myplot <- renderPlot({
    plot1()
  })
  
  #Download
  output$downloadPlot <- downloadHandler(
    filename = function() {
      return("Plot.png")
    },
    content = function(file) {
      png(file)
      print(plot1())
      dev.off()
    })
  
  #Write csv
  
  eventReactive(input$downloadPlot, {
    dat <- as.data.frame(c(input$num_var_1, input$num_var_2))
    write.csv(dat, "C:/dat.csv", row.names = FALSE)
  })
  }

shinyApp(ui, server)

CodePudding user response:

library(shiny)
library(ggplot2)
library(AlphaPart)
library(spsComps)


ui <- fluidPage(
    selectInput("var1","Select var1", choices = names(iris)),
    selectInput("var2","Select var2", choices = names(iris)),
    plotOutput("myplot"),
    downloadLink("downloadPlot", label = icon("download")))

server <- function(input, output, session) {
    
    data <- reactive(iris)
    var1 <- reactive({input$var1})
    var2 <- reactive({input$var2})
    
    # Genearte plot
    draw_boxplot <- function(data, var1, var2){
        ggplot(data=data(), aes(x=.data[[input$var1]], y = .data[[input$var2]])) 
            geom_boxplot() 
    }
    
    plot1 <- reactive({
        req(data(), input$var1, input$var2)
        draw_boxplot(data(), var1(), var2())
    })
    
    output$myplot <- renderPlot({
        plot1()
    })
    
    #Download
    downloaded <- reactiveVal(0)
    output$downloadPlot <- downloadHandler(
        filename = function() {
            return("Plot.png")
        },
        content = function(file) {
            png(file)
            print(plot1())
            dev.off()
            on.exit({spsComps::incRv(downloaded)})
        })
    #Write csv
    observeEvent(downloaded(), {
        dat <- as.data.frame(c(input$num_var_1, input$num_var_2))
        utils::write.csv(dat, "dat.csv", row.names = FALSE)
        print("File saved")
    }, ignoreInit = TRUE)
}

shinyApp(ui, server)
  1. Unfortunately, you can't observe download event. So here we do, introduce another reactiveVal which we can change inside the download event so we will know if the download button has been clicked.
  2. spsComps::incRv is a short hand function for downloaded(isolate(downloaded()) 1), so it increase the reactiveVal every time by one.
  3. use on.exit on the end to make sure this happens only when the plot is successful.
  4. Instead of using eventReactive, observeEvent should be used since you are not returning any value but just write a file.
  • Related