5

Problem

When including a HTML document rendered from RMarkdown in a ShinyApp using shinydashboard, the HTML document is only rendered correctly when the setting "self_contained:" in the YAML chunk of the RMarkdown file is set to true. However, doing this causes you to be unable to select tabItems from the sidebarMenu in shinydashboard.

Conversely, when the setting "self_contained:" is set to false, elements of the HTML document such as plots and a floating table of contents are missing (non-HTML elements present in the additional files), but you are able to select tabItems from the sidebarMenu, and the rest of the app works fine.

Ideally, you would be able to include a fully functioning HTML file rendered from RMarkdown in shinydashboard, whilst retaining functionality in the rest of the app.

My previous post regarding how to include a HTML in a basic Shiny app refers to this additional problem (Bibliography not working when rendering a R Markdown document within an R Shiny App).

Please find a minimum reproducible example below.

Minimum reproducible example

RMarkdown file

RMarkdownFile.Rmd

---
title: "RMarkdownFile"
author: "Test Author"
date: "15/10/2020"
output: 
  html_document:
    toc: true
    toc_float: true
    number_sections: true
    self_contained: true
bibliography: bibliography.bib
link-citations: yes
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)

library(ggplot2)

```


# Statement

ggplot2 [@wickham2016ggplot2] is a great package!

```{r plot, message=FALSE}

ggplot2::ggplot(data = mpg) + 
  ggplot2::geom_point(mapping = aes(x = displ, y = hwy))
  
```

## References

Bibliography

bibliography.bib

@book{wickham2016ggplot2,
  title={ggplot2: elegant graphics for data analysis},
  author={Wickham, Hadley},
  year={2016},
  publisher={springer}
}

Shiny app

app.R

library(shiny)
library(shinydashboard)
library(rmarkdown)

rmarkdown::render("RMarkdownFile.Rmd")

ui <- dashboardPage(
  
  dashboardHeader(title = "Test"),
  
  dashboardSidebar(
    sidebarMenu(id = "sidebarmenu",
                
                menuItem("Test Section 1", tabName = "testitem1",
                         menuSubItem("Test Section 1a", tabName = "testitem1a"),
                         menuSubItem("Test Section 1b", tabName = "testitem1b")
                         ),
                
                menuItem("Test Section 2", tabName = "testitem2",
                         menuSubItem("Test Section 2a", tabName = "testitem2a"),
                         menuSubItem("Test Section 2b", tabName = "testitem2b")
                         ),
                
                menuItem("Test Section HTML", tabName = "testitemhtml"
                         )
                )
    ),
  
  dashboardBody(
    
    tabItems(
    
      tabItem(tabName = "testitem1a",
              fluidRow(
                box(title = "Test Section 1a",
                    width = 12))
              ),
              
      tabItem(tabName = "testitem1b",
              fluidRow(
                box(title = "Test Section 1b",
                    width = 12))
              ),
              
      tabItem(tabName = "testitem2a",
              fluidRow(
                box(title = "Test Section 2a",
                    width = 12))
              ),
              
      tabItem(tabName = "testitem2b",
              fluidRow(
                box(title = "Test Section 2b",
                    width = 12))
              ),
              
      tabItem(tabName = "testitemhtml",
              fluidPage(
                box(title = "Test Section HTML",
                    width = 12,
                    includeHTML("RMarkdownFile.html")))
              )
      )
    )
)
  
  
  

server <- function(input, output) { }

shinyApp(ui, server)

Any help in solving this problem would be greatly appreciated!

ZekeMarshall
  • 131
  • 5
  • 2
    Use an `iframe` (`tags$iframe`), not `includeHTML`. – Stéphane Laurent Oct 16 '20 at 12:11
  • Hi Stéphane, thanks for your reply. This worked perfectly, I've updated my post above to include the implementation of your solution in my minimum reproducible example. Thanks again! – ZekeMarshall Oct 16 '20 at 15:57
  • 1
    You can post an answer to your own question. It's not forbidden and this would be cleaner :) – Stéphane Laurent Oct 16 '20 at 19:12
  • Thanks Stéphane, I've now moved the solution to the answers :) – ZekeMarshall Oct 17 '20 at 12:58
  • 2
    Good :) FYI, `includeHTML` does not work because it includes all the contents of the files, including the `head` tag which loads JavaScript libraries, CSS, and the `body` and `html` tags which are already present in the Shiny app and these tags must be unique. This causes a terrific mess. On the other hand, `iframe` works because the contents of an `iframe` are totally isolated from the other contents of the document. – Stéphane Laurent Oct 17 '20 at 13:14
  • Thanks, that makes complete sense! This is my first Shiny App so its been a steep learning curve, but the fact that it could be done so easily with the tags$iframe approach shows how accessible Shiny really is. Thanks again :) – ZekeMarshall Oct 18 '20 at 09:59

1 Answers1

2

This question was resolved by Stéphane in the comments above!

Please find a working version of the minimum reproducible example app.R below:

library(shiny)
library(shinydashboard)
library(rmarkdown)

rmarkdown::render("RMarkdownFile.Rmd")

ui <- dashboardPage(
  
  dashboardHeader(title = "Test"),
  
  dashboardSidebar(
    sidebarMenu(id = "sidebarmenu",
                
                menuItem("Test Section 1", tabName = "testitem1",
                         menuSubItem("Test Section 1a", tabName = "testitem1a"),
                         menuSubItem("Test Section 1b", tabName = "testitem1b")
                         ),
                
                menuItem("Test Section 2", tabName = "testitem2",
                         menuSubItem("Test Section 2a", tabName = "testitem2a"),
                         menuSubItem("Test Section 2b", tabName = "testitem2b")
                         ),
                
                menuItem("Test Section HTML", tabName = "testitemhtml"
                         )
                )
    ),
  
  dashboardBody(
    
    tabItems(
    
      tabItem(tabName = "testitem1a",
              fluidRow(
                box(title = "Test Section 1a",
                    width = 12))
              ),
              
      tabItem(tabName = "testitem1b",
              fluidRow(
                box(title = "Test Section 1b",
                    width = 12))
              ),
              
      tabItem(tabName = "testitem2a",
              fluidRow(
                box(title = "Test Section 2a",
                    width = 12))
              ),
              
      tabItem(tabName = "testitem2b",
              fluidRow(
                box(title = "Test Section 2b",
                    width = 12))
              ),
              
      tabItem(tabName = "testitemhtml",
              fluidPage(
                htmltools::tags$iframe(src = "RMarkdownFile.html", width = '100%',  height = 1000,  style = "border:none;"))
              )
      )
    )
)
  
  
  

server <- function(input, output) { }

shinyApp(ui, server)

For this solution to work the "RMarkdownFile.html" file must be manually placed in a folder called "www" in the Shiny app directory, unless the "RMarkdownFile.Rmd" file is rendered directly to this "www" folder.

ZekeMarshall
  • 131
  • 5