42

Problem

Is there a way to insert (and evaluate) an RMarkdown script in a shiny application. (Note, I am not looking for a shiny application in RMarkdown that is explained here, nor am I looking for Markdown scripts in shiny (see Shiny Gallery Markdown))

I am building an application that has text, equations, code-chunks, plots, and interactive elements. For convenience I use Markdown files for the text and equations and would like to have a plot sometimes in between (i.e. write most stuff in RMarkdown). As the shiny-app is more complex (I use shinydashboard including many of its unique features), I would prefer an option that does not use the approach described in the first link.

A minimum working example would be:

R-file:

library(shiny)

ui <- shinyUI(
  fluidPage(
    includeMarkdown("RMarkdownFile.rmd")
  )
)
server <- function(input, output) {}

shinyApp(ui, server)

and "RMarkdownFile.rmd" in the same folder:

This is a text

$$ E(x) = 0 $$ 

```{r, eval = T}
plot(rnorm(100))
```

Result:

Shiny App

Target

What I want to have is the output if I knit the rmd-file: RMarkdown HTML page

Specifically, I want to get the evaluation of the code-chunks (plot something...), and I want to get the rendered math equations.

Any ideas?

Edited Solution

Thanks to the input of @Bunk, I chose to render all rmd files to md files with the command knit and then include the md files in the shiny app (I use markdown instead of html as the latter produced some issues with equations). Lastly, the includeMarkdown is wrapped in withMathJax to ensure the proper display of equations.

The final code looks like this:

library(shiny)
library(knitr)

rmdfiles <- c("RMarkdownFile.rmd")
sapply(rmdfiles, knit, quiet = T)

ui <- shinyUI(
    fluidPage(
        withMathJax(includeMarkdown("RMarkdownFile.md"))
  )
)
server <- function(input, output) { }

shinyApp(ui, server)
Rorschach
  • 31,301
  • 5
  • 78
  • 129
David
  • 9,216
  • 4
  • 45
  • 78

2 Answers2

30

I think knitting it and rendering a UI should work.

library(shiny)
library(knitr)

ui <- shinyUI(
    fluidPage(
        uiOutput('markdown')
  )
)
server <- function(input, output) {
    output$markdown <- renderUI({
        HTML(markdown::markdownToHTML(knit('RMarkdownFile.rmd', quiet = TRUE)))
    })
}

shinyApp(ui, server)
Rorschach
  • 31,301
  • 5
  • 78
  • 129
  • Good idea, I was just playing around with `includeHTML` after using `knitr` to create a HTML file. – David Nov 03 '15 at 13:39
  • I was thinking about that too, you could probably render as the application loads and do that instead. Doing this allows you to evaluate the code chunks in specific environments. I don't know if that is useful in this case. – Rorschach Nov 03 '15 at 13:41
  • One more question though, does your equation render properly? – David Nov 03 '15 at 13:55
  • yea it does for me, I ran it on firefox. I think you just need to make sure that the mathjax script is getting loaded. – Rorschach Nov 03 '15 at 14:10
  • 1
    you could mess around with the `withMathJax()` function. – Rorschach Nov 03 '15 at 14:16
  • @David sorry, it looks like your edit was rejected since I was on here, I would have accepted it. One thing I would change, instead of setting working directory, use a relative path if possible. – Rorschach Nov 03 '15 at 19:17
12

As per @elevendollar's request, this is what I ended up using:

library(shiny)
library(knitr)

rmdfiles <- c("file1.Rmd", "file2.Rmd")
mdfiles <- gsub("Rmd$", "md", rmdfiles)

a <- lapply(rmdfiles, knit, quiet = T)

ui <- shinyUI(
  fluidPage(
    withMathJax(
      # loop over the files and create one tabPanel for each file
      do.call(tabsetPanel,
              lapply(mdfiles, function(f) tabPanel(f, includeMarkdown(f))))
    )
  )
)
server <- function(input, output) { }

shinyApp(ui, server)
David
  • 9,216
  • 4
  • 45
  • 78
  • You used `sapply` so I presumed it works for more than 1 length of `rmdfiles`. But in the `includeMarkdown("RMarkdownFile.md"))` you use a hardcoded file name. Why? Can you please make it a vector to make the answer complete for a more general vector scenario ? Thanks – Lazarus Thurston Sep 08 '21 at 09:42
  • 2
    Better late than never; done! – David Aug 01 '22 at 09:31