ZBauc
ZBauc

Reputation: 163

RShiny Download Button Within RMarkdown

I can't seem to get the shiny downloadButton to work in an rmarkdown document with runtime: shiny. Here is an example similar to what I am doing.

 ---
 title: "R Document"
 runtime: shiny
 ---

 ```{r, echo = FALSE}
 numericInput("SS", "Selecr SS", min = 1, max = 100, value = 1)

 RandomSample <- reactive({
   data.frame(X = rnorm(100), Y = rnorm(100))
 })

 downloadButton("download", "Download")

 renderPlot({
   plot(RandomSample()[(1:input$SS), "X"], RandomSample()[(1:input$SS), "Y"])
 })

 renderTable({
   RandomSample()[(1:input$SS),]
 })
 ```

I'd like the download button to download RandomSample(), but I can't even get the downloadButton to show up.

Upvotes: 5

Views: 3996

Answers (2)

Tom Greenwood
Tom Greenwood

Reputation: 1672

There's something a bit weird with downloadButton. If you look at the function it's:

function (outputId, label = "Download", class = NULL, ...)  {
aTag <- tags$a(id = outputId, class = paste("btn btn-default shiny-download-link", 
    class), href = "", target = "_blank", download = NA, 
    icon("download"), label, ...)
}

whereas downloadLink is:

function (outputId, label = "Download", class = NULL, ...) {
    tags$a(id = outputId, class = paste(c("shiny-download-link", 
        class), collapse = " "), href = "", target = "_blank", 
        download = NA, label, ...)
}

What that means is the return value of downloadButton is invisible, so it won't produce the html to work in markdown (I'm sure that's probably by design for shiny, but if someone can explain why I'd like to know). You can change this behaviour by writing a new function:

downloadButtonRmd <- function (outputId, label = "Download", class = NULL, ...)  {
     tags$a(id = outputId, class = paste("btn btn-default shiny-download-link", 
        class), href = "", target = "_blank", download = NA, 
        icon("download"), label, ...)
 }

Which has visible output. This might be useful in the case where you have multiple downloads from one document (which is what led me here)

---
title: "R Document"
runtime: shiny
output: html_document
---


```{r}
downloadButtonRmd <- function (outputId, label = "Download", class = NULL, ...)  {
     tags$a(id = outputId, class = paste("btn btn-default shiny-download-link", 
        class), href = "", target = "_blank", download = NA, 
        icon("download"), label, ...)
 }
```



```{r, echo=FALSE}

numericInput("SS1", "Select SS1", min = 1, max = 100, value = 1)
numericInput("SS2", "Select SS2", min = 1, max = 100, value = 1)

downloadButtonRmd("down1", label = "Download1")
downloadLink("down2", label = "Download2")


RandomSample <- reactive({
   data.frame(X = rnorm(100), Y = rnorm(100))
 })

output$down1 <- downloadHandler(filename = function() { 
    return(paste('Example', input$SS1, '.csv', sep=''))

 }, content = function(file) {
   write.csv(RandomSample(), file)
 })

output$down2 <- downloadHandler(filename = function() { 
    return(paste('Example', input$SS2, '.csv', sep=''))

 }, content = function(file) {
   write.csv(RandomSample(), file)
 })

renderPlot({
   plot(RandomSample()[(1:input$SS1), "X"], RandomSample()[(1:input$SS1), "Y"])
 })

renderPlot({
   plot(RandomSample()[(1:input$SS2), "X"], RandomSample()[(1:input$SS2), "Y"])
 })

renderTable({
   RandomSample()[(1:input$SS1),]
 })

renderTable({
   RandomSample()[(1:input$SS2),]
 })


 ```

Upvotes: 4

Jeremy Farrell
Jeremy Farrell

Reputation: 1491

I think what you are looking for is downloadHandler.

Here is your example with it working:

---
title: "R Document"
runtime: shiny
output: html_document
---
```{r, echo=FALSE}

 numericInput("SS", "Selecr SS", min = 1, max = 100, value = 1)

 RandomSample <- reactive({
   data.frame(X = rnorm(100), Y = rnorm(100))
 })

 downloadHandler(filename = function() { 
    return(paste('Example', input$SS, '.csv', sep=''))

 }, content = function(file) {
   write.csv(RandomSample(), file)
 })

 renderPlot({
   plot(RandomSample()[(1:input$SS), "X"], RandomSample()[(1:input$SS), "Y"])
 })

 renderTable({
   RandomSample()[(1:input$SS),]
 })
 ```

Note that your filename will not be respected while testing in RStudio, but when running in a browser it will.

Upvotes: 5

Related Questions