0

I want to generate a report that include a plot from another module, but my code does not work.

I have checked few examples from other shiny developers, but my code does not work.

As far as I understand, I need to:

(1) return the plot the plot module

(2) pass it to the download server

(3) also need to include it in the main server (I don't understand the logic here, I need your help for explanation)

My minimal example:

# Module 1,
plot_ui <- function(id) {
  ns <- NS(id)
  tagList(
    plotOutput(ns("plot"))
    )
  }

plot_server <- function(id) {
  moduleServer(id, function(input, output, session) {
    myplot <- reactive({plot(x = mtcars$wt, y = mtcars$mpg)})
    output$plot <-renderPlot({
      myplot()
    })
    return(myplot)
  })
}

# Module 2
download_ui <- function(id) {
  ns <- NS(id)
  tagList(
    downloadButton(outputId = ns("report_button"),
                   label = "Generate report"
                   )
    )
}

download_server <- function(id, myplot) {
  moduleServer(id, function(input, output, session){
    output$report_button<- downloadHandler(
      filename = "report.html",
      content = function(file) {
        tempReport <- file.path(tempdir(), "myRport.Rmd")
        file.copy("myReport.Rmd", tempReport, overwrite = TRUE)
        params <- list(plot1 = myplot())
        rmarkdown::render(tempReport,
                          output_file = file,
                          params = params
                          )
        }
      )
    }
  )
}


# Application
library(shiny)
app_ui <- function() {
  fluidPage(
    plot_ui("plot_ui_1"),
    download_ui("download_ui_2")
    )
}

app_server <- function(input, output, session) {
  getPlot <- plot_server("plot_ui_1")
  download_server("download_ui_2", myplot = getPlot)
}

shinyApp(app_ui, app_server)

My markdown file

---
title: "Test"
output: html_document
params:
  plot1: NA
---

```{r}
params$plot1
Wang
  • 1,314
  • 14
  • 21
  • 1
    [Here's how to ask a proper "Where's the bug / Fix my code" question](https://meta.stackoverflow.com/a/253788/11107541). Can you please read it and apply what you learn to improve your question? Hint: look at your title. Also, don't put "non-organic" tags in your title. Please see [What should I keep out of my posts and titles?](https://meta.stackexchange.com/q/131009/997587) and [ask]. – starball Jan 02 '23 at 20:43
  • 1
    Does this answer your question? [How to update shiny module with reactive dataframe from another module](https://stackoverflow.com/questions/68584478/how-to-update-shiny-module-with-reactive-dataframe-from-another-module) – Limey Jan 02 '23 at 22:53

1 Answers1

1

Basically you have done everything right. However, to make you code work you have to render your Rmd in a new environment by adding envir = new.env(parent = globalenv()) to rmarkdown::render. See e.g. Generating downloadable reports. Moreover TBMK you can't pass a base R plot to an Rmd via params, i.e. while your code works no plot will be displayed in the rendered report. That's why I switched to ggplot2:

# Module 1,
plot_ui <- function(id) {
  ns <- NS(id)
  tagList(
    plotOutput(ns("plot"))
  )
}

plot_server <- function(id) {
  moduleServer(id, function(input, output, session) {
    myplot <- reactive({
      #plot(x = mtcars$wt, y = mtcars$mpg)
      ggplot(mtcars, aes(wt, mpg)) +
        geom_point()
    })
    output$plot <-renderPlot({
      myplot()
    })
    return(myplot)
  })
}

# Module 2
download_ui <- function(id) {
  ns <- NS(id)
  tagList(
    downloadButton(outputId = ns("report_button"),
                   label = "Generate report"
    )
  )
}

download_server <- function(id, myplot) {
  moduleServer(id, function(input, output, session){
    output$report_button<- downloadHandler(
      filename = "report.html",
      content = function(file) {
        tempReport <- file.path(tempdir(), "myRport.Rmd")
        file.copy("myReport.Rmd", tempReport, overwrite = TRUE)
        params <- list(plot1 = myplot())
        rmarkdown::render(tempReport,
                          output_file = file,
                          params = params,
                          envir = new.env(parent = globalenv())
        )
      }
    )
  }
  )
}

# Application
library(shiny)
library(ggplot2)

app_ui <- function() {
  fluidPage(
    plot_ui("plot_ui_1"),
    download_ui("download_ui_2")
  )
}

app_server <- function(input, output, session) {
  getPlot <- plot_server("plot_ui_1")
  download_server("download_ui_2", myplot = getPlot)
}

shinyApp(app_ui, app_server)

enter image description here

stefan
  • 90,330
  • 6
  • 25
  • 51
  • Dear @stefan, sorry to bother you again. The current code works, but I still cannot generate report. There is only one plot in the test code, but the report generation process never ends. I don't know what the problem is. |..................................................................................... | 67% label: Testplot – Wang Jan 03 '23 at 12:26
  • Hm. Weird. I just checked again and it works fine on my machine. No clue what might be the issue. – stefan Jan 03 '23 at 12:34
  • 1
    Hi @stefan. It works now after I restart my PC. Thanks a lot for your kind help! – Wang Jan 03 '23 at 12:37