Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Progress bar for kniting documents via shiny

I am trying to put a progress bar around my shiny downloadHandler(). The progress bar should show the render status of the rmarkdown HTML

I found this infomation on GitHub (https://github.com/rstudio/shiny/issues/1660) but could not get it to work. If I define no environment the file can not be knitted.

app.R

library(shiny)
library(rmarkdown)

ui <-  fluidPage(
  sliderInput("slider", "Slider", 1, 100, 50),
  downloadButton("report", "Generate report"),
  textOutput("checkrender")
)
server <-  function(input, output, session) {
  output$checkrender <- renderText({
     if (identical(rmarkdown::metadata$runtime, "shiny")) {
       TRUE
     } else {
       FALSE
     }
  })

  output$report <- downloadHandler(
    filename = "report.html",
    content = function(file) {

      tempReport <- file.path(tempdir(), "report.Rmd")
      file.copy("report.Rmd", tempReport, overwrite = TRUE)

      params <- list(n = input$slider)

      rmarkdown::render(tempReport, 
                        output_file = file,
                        params = params,
                        envir = new.env(parent = globalenv())
      )
    }
  )
}

shinyApp(ui = ui, server = server)

report.Rmd

---
title: "Dynamic report"
output: html_document
params:
  n: NA
---

```{r}
params$n
```

A plot of `params$n` random points.

```{r}
 plot(rnorm(params$n), rnorm(params$n))
```
like image 842
Florian Avatar asked Dec 13 '22 12:12

Florian


1 Answers

Your solution was quite close!

Two problems I see with your code:

  • You've left out the withProgress call in your downloadHandler code
  • The test for whether you're running in a shiny environment, if (identical(rmarkdown::metadata$runtime, "shiny")), needs to go in your .Rmd file. You enclose any calls to increment/set the progress bar in this test, otherwise the .Rmd code will produce errors like Error in shiny::setProgress(0.5) : 'session' is not a ShinySession object.

The below reworking of your code should work:

app.R

library(shiny)
library(rmarkdown)

ui <-  fluidPage(
  sliderInput("slider", "Slider", 1, 100, 50),
  downloadButton("report", "Generate report"),
  textOutput("checkrender")
)
server <-  function(input, output, session) {
  output$checkrender <- renderText({
    if (identical(rmarkdown::metadata$runtime, "shiny")) {
      TRUE
    } else {
      FALSE
    }
  })

  output$report <- downloadHandler(
    filename = "report.html",
    content = function(file) {
      withProgress(message = 'Rendering, please wait!', {
        tempReport <- file.path(tempdir(), "report.Rmd")
        file.copy("report.Rmd", tempReport, overwrite = TRUE)

        params <- list(n = input$slider)

        rmarkdown::render(
          tempReport,
          output_file = file,
          params = params,
          envir = new.env(parent = globalenv())
        )
      })
    }
  )
}

shinyApp(ui = ui, server = server)

report.Rmd

---
title: "Dynamic report"
output: html_document
params:
  n: NA
---

```{r}
params$n

if (identical(rmarkdown::metadata$runtime, "shiny"))
  shiny::setProgress(0.5)  # set progress to 50%
```

A plot of `params$n` random points.

```{r}
plot(rnorm(params$n), rnorm(params$n))

if (identical(rmarkdown::metadata$runtime, "shiny"))
  shiny::setProgress(1)  # set progress to 100%
```
like image 64
jsavn Avatar answered Dec 26 '22 14:12

jsavn