3
votes

Shiny experts!

In our application we have download button for plot downloading. The button is working only when some data are loaded and processed. When you push the button before, there is an error message from plotting function, because it has no data.

content = function(file) {
            r <- rChart_line_plot(follow_view_func(),log_scale = input$checkbox_log_scale_plot,isRel = input$checkboxRelativeTab2)
            r$save(file, standalone = TRUE)
        }

We want to make our app foolproof and error-free. Is there any possible way to send to downloadHandler's content "NULL"? This don't work.

content = function(file) {
          if ( "our data are ready for printing" ) {
            r <- rChart_line_plot(follow_view_func(),log_scale = input$checkbox_log_scale_plot,isRel = input$checkboxRelativeTab2)
            r$save(file, standalone = TRUE)
          } else {
            NULL
          }
        }

And we're getting:

Error opening file: 2
Error reading: 9

Is there something like validate() function with even information for user "Please load file first"

Thank You a lot.

1
Would it possible to post the rest of your application code - i.e. the complete ui.R and server.R files? - nrussell
Each of them have more than 1000 lines.. I'm probably asking for help especially with downloadHandler() function - if there any way to silence its errors. - user1991825

1 Answers

4
votes

You are correct that you want a validate statement. Here is a link with descriptions from the RStudio team. This will allow you to have a more informative error message. Your complete downloadHandler function would look something like the following. Note that this assumes your dataset could be null.

output$Download <- downloadHandler(
                filename = function() {
                    paste("test.png",sep="")
                },
                content = function(file) {
                    myData <- follow_view_func()
                    validate(
                        need(!is.null(myData), "Please select valid dataset")
                    )
                    r <- rChart_line_plot(myData,log_scale = input$checkbox_log_scale_plot,isRel = input$checkboxRelativeTab2)
                    r$save(file, standalone = TRUE)
                }
            )

Here is a complete reproducible example with the iris dataset.

library(shiny)
library(rCharts)
runApp(
    list(
        ui = pageWithSidebar(
            headerPanel("Using 'validate' for useful error messages"),

            sidebarPanel(
                selectInput("dataset", "Choose a dataset:", 
                            choices = c("null", "iris")),
                selectInput(inputId = "x",
                            label = "Choose X",
                            choices = c('SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth'),
                            selected = "SepalLength"),
                selectInput(inputId = "y",
                            label = "Choose Y",
                            choices = c('SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth'),
                            selected = "SepalWidth"),
                downloadButton("Download")
            ),
            mainPanel(
                showOutput("myChart", "polycharts")
            )
        ),

        server = function(input, output) { 

            datasetInput <- reactive({
                switch(input$dataset,
                       "iris" = iris,
                       "null" = NULL)
            })

            myChart <- reactive({
                myData <- datasetInput()
                validate(
                    need(!is.null(myData), "Please select valid dataset")
                )
                names(myData) = gsub("\\.", "", names(myData))
                p1 <- rPlot(input$x, input$y, data = myData, color = "Species", 
                            facet = "Species", type = 'point')
                p1$addParams(dom = 'myChart')
                return(p1)
            })

            output$myChart <- renderChart({myChart()})

            output$Download <- downloadHandler(
                filename = function() {
                    paste("test.png",sep="")
                },
                content = function(file) {
                    p1 <- myChart()
                    p1$save(file, standalone = TRUE)
                }
            )
        }
        )
    )

UPDATE

As per the OP request, it may be ideal to have no error whatsoever with the download button. The only solution I could come up with is to make the button a conditionalPanel. This intuitively makes sense to me because why would you download if there is nothing on the screen? The only change in the code above needed for this is to change:

downloadButton("Download")

to

conditionalPanel("output.myChart", downloadButton("Download"))

Now the download button will only be present when a valid chart is created.