rstudio / shiny

Easy interactive web applications with R

Home Page:https://shiny.posit.co/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

question: render multiple dynamic rmarkdown documents inside a shiny app?

vnijs opened this issue · comments

To include an rmarkdown document with (shiny) inputs I currently break-up the Rmd file into chunks because interactive elements don't work when rendering the document from within a shiny app (AFAIK). At least, I get input not found if I try to use the value of a slider to make a plot (using Knitr). And Error in handlers$add(handler, key, tail) : Key / already in use if I use rmarkdown::run(path_to_file)

Example below:

Shiny code called from ui.R:

output$mini_case_1 <- renderUI({
  tagList(
    # rmarkdown::run("./cases/case1/01_test.Rmd"),
    inclRmd("./cases/case1/01_test.Rmd") 
  )
})

Where: 01_test.Rmd contains:

sliderInput("bins", "Number of bins:", min = 1, max = 50, value = 30)

renderPlot({
  x <- faithful[, 2]
  bins <- seq(min(x), max(x), length.out = input$bins + 1)         ## here I get "input not found"
  # bins <- seq(min(x), max(x), length.out = 10 + 1)          ## this works
  hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
inclRmd <- function(path) {
  paste(readLines(path, warn = FALSE), collapse = '\n') %>%
  knitr::knit2html(text = ., fragment.only = TRUE, options = "",
                   stylesheet=file.path(r_path,"../www/empty.css")) %>%
    gsub("&lt;!--/html_preserve--&gt;","",.) %>%
    gsub("&lt;!--html_preserve--&gt;","",.) %>%
    HTML %>%
    withMathJax
}

My question is related to this SO question. Comments?

http://stackoverflow.com/questions/28551267/use-multiple-r-markdown-files-in-shiny-tabs/30766806#30766806

knit2html() is for R Markdown v1 only (http://stackoverflow.com/q/29518223/559676) and shiny docs do not work in R Markdown v1. In theory, you should call rmarkdown::render(), but I don't think it works for child documents. What you might be able to do is

```{r child='./cases/case1/01_test.Rmd'}

I'm not completely sure if this works.

@yihui I'm not sure how or where to use the child argument given what I have in mind. To clarify I put a minimal shiny app together at https://github.com/vnijs/shiny-site

The goal is to render multiple files like full.Rmd that are each linked to a different menu item in the navbar. Using knitr I can use sliderInput and renderPlot but I can't use the value from the slider in renderPlot (i.e., get an error input not found). See the Statistics tab.

What I do now is break the rmd file into part1.Rmd and part2.Rmd and put the code for the interactive plot in ui.R and server.R. See the Probability tab.

Breaking up the file is not a big deal if there are only a few interactive elements but with many (e.g., quizzes) it is awkward.

Suggestions?

@yihui I found an approach to combine multiple rmarkdown files with iteractive elements into a shiny-site without having to split up the files into chunks. See https://github.com/vnijs/shiny-site. It works by using Shiny's renderUI functionality and evaluating the rmarkdown file with Knitr in the shinyServer environment.

Is this still the only approach for it?
I'd like to create a website/blog based on shiny and would really welcome any solution that are stable 😄

@zippeurfou If the approach I suggested not stable? See also discussion here: http://stackoverflow.com/a/30897663/1974918

@vnijs Sorry I did not word it correctly. Your approach is really good and I am glad you did it. I just believe that it would be great if they include an official helper method to do so or in Rstudio to make it easier.
I'd love to mix this with some ghost design to make it a shiny project blog !

Hi there, I've done a similar approach and I was really happy as I was able to fully use the shiny inputs to get my markdown updated and performing. You can see the code here along with a question I head.
Everything goes well but I am not able to download the final doc either in pdf or html or word. I am really stuck as this is a key task for the users.
I was using this in the server side:
output$downloadData <- downloadHandler( filename = function() { paste('my-report', sep = '.', switch( input$format, PDF = 'pdf', HTML = 'html', Word = 'docx' )) },
content = function(file) {
src <- normalizePath('RMarkdown_pdf1.Rmd')

  # temporarily switch to the temp dir, in case you do not have write
  # permission to the current working directory
  owd <- setwd(tempdir())
  on.exit(setwd(owd))
  file.copy(src, 'RMarkdown_pdf1.Rmd')

  library(rmarkdown)
  out <- render('RMarkdown_pdf1.Rmd', switch(
    input$format,
    PDF = pdf_document(), HTML = html_document(), Word = word_document()
  ))
  file.rename(out, file)
}

)
`

But I am getting a message saying cannot open the connection. The logfile seems to suggest that it can't find the functions I sourced within the Markdown.
Please help.

@vnijs It looks like you were able to get this to work in your shiny-site example, via renderUI. Would you still consider your original issue a bug in Shiny, or a feature request?

If not, would you mind closing this issue when you next have the opportunity? Thanks in advance for considering this ancient issue one more time. We're just trying to dig ourselves out of issue bankruptcy, and your assistance is much appreciated 😄

@alandipert We have used the approach in shiny-site with our students for a number of years now and it works, even-though perhaps a bit "hacky". Will close.