rplotlyr-markdownflexdashboardhtmltools

Generating a flexdashboard with plotly plots in a for loop but unable to get desired result when accessing elements in a list of tagLists in a loop


I'm trying to write this RMarkdown file that generates a dashboard using flexdashboard, with interactive plots via plotly, using a for loop to generate the appropriate RMarkdown code (e.g. using cat(insert markdown/text here) and results=as.is).

I used a nested for loop to generate j sets of plots + the RMarkdown that separates them as components, to go onto j pages. Originally, the plotly objects weren't printing if I wanted to output them among the RMarkdown directly in the for loop, so I converted the RMarkdown to HTML and saved that + the plotly output in a tagList within the for loop. Then I saved these tagLists within a vector to later print outside of the for loop.

The problem I'm facing is that this works when I reference the elements of the outside list using $, but not using brackets. I would prefer to use brackets so that I can use a for loop (I don't want to have to change the code if the element names change).

Below is somewhat of a (not self-contained, sorry) sketched out reproduction of what I'm describing. Any insight into why these methods yield different results?

totalhtml <- c()

# generate content for each of j pages
for (j in vector_of_categories){
  stuff_in_category_j <- # vector of things within category
  
   html_j <- htmltools::tagList()
  
  for (i in stuff_in_category_j){
    # cut out the code to make all the contents/plot
    # but result to generate components is something like:    
    html_j[[i]] <- tagList(HTML(markdown::mark(text = paste("###", title_i, "\n\n"))), plot_i)
  }
  
  totalhtml[[j]] <- html_j
} 

I have names(totalhtml): "A" "B" "C" And the following attempts to generate my dashboard

# {r results = 'asis'}
# works as desired- 3 pages, each with various plot components

cat(names(totalhtml)[1], "\n==========\n")
totalhtml$`A`

cat(names(totalhtml)[2], "\n==========\n")
totalhtml$`B`

cat(names(totalhtml)[3], "\n==========\n")
totalhtml$`C`
#{r results = "asis"}
#nothing prints on each of 3 pages

for(k in names(totalhtml)){
  cat(k, "\n=========\n")
  totalhtml[[k]]
}
#{r results = "asis"}
#component headers print, but no plots

for(k in names(totalhtml)){
  cat(k, "\n=========\n")
  print(totalhtml[k])
  #same for print(totalhtml[[k]])
}

Solution

  • As you did not provide a working or runnable example one can only guess what's the issue with your code. Below is a minimal working example base on the mtcars dataset which uses a nested for loop to create a page for each category of cyl and fills each page with two plotly charts for each category of am:

    ---
    title: "My Dash"
    output: 
      flexdashboard::flex_dashboard:
        orientation: rows
        vertical_layout: fill
    ---
    
    ```{r setup, include=FALSE}
    library(flexdashboard)
    library(plotly)
    ```
    
    ```{r init-js-deps, include=FALSE}
    plot_ly()
    ```
    
    ```{r results='asis'}
    mtcars_split <- mtcars |>
      split(~cyl) |>
      lapply(split, ~am)
    names(mtcars_split) <- LETTERS[seq_along(mtcars_split)]
    
    for (j in names(mtcars_split)) {
      cat(sprintf("%s\n==========\n", j))
      for (i in names(mtcars_split[[j]])) {
        cat(sprintf("### %s\n\n", i))
        print(
          htmltools::tagList(
            plot_ly(mtcars_split[[j]][[i]], x = ~mpg, y = ~hp)
          )
        )
      }
    }
    ```
    

    enter image description here