Recommended way to initialize JS renderer in 'asis' R Markdown chunk
Asked Answered
S

3

7

'asis' chunks are very useful to output a list of objects in a Markdown document, see following examples : Highcharter, DT, Leaflet, ...

However, in the above examples, the list of object won't print if the renderer hasn't been called once in a previous chunk, so that it gets initialized : this is a tricky workaround, and I found the solution more by trial / error than by finding it in documentation.

This is a reproducible issue also posted on https://github.com/rstudio/rmarkdown/issues/1877 :

---
title: "Test"
output:
  html_document
---



```{r,echo=F}
library(DT)
library(rmarkdown)
library(purrr)
library(knitr)

df_list <- list("cars" = mtcars, "flowers" = iris)

knitr::opts_chunk$set(echo = FALSE, warning = FALSE, message = FALSE)
```

```{r}
# If this first initialization isn't run, tabs won't print
DT::datatable(data.frame())
```

# Test tabs {.tabset}

```{r, results='asis' }
imap(df_list, ~{
  cat('## Subtab ',.y,'\n')
  cat('\n')
  DT::datatable(.x) %>%
    htmltools::tagList() %>% as.character() %>% cat() })

```
 

  
Saga answered 22/8, 2020 at 8:44 Comment(5)
I'm not sure if that fits here (I think it's a bit different use case and I'm not overly familiar with the Rmarkdown), but for DT I used the option to define my own knit_print.data.frame method to use DT for data.frames following this isse: github.com/yihui/printr/issues/33 However, I haven't tested it with lists of data.frames yetSophister
Thanks @Starja for the link. I tried to include the print method, but it didn't initialize the JS renderer.Saga
I'm not sure if this is related, you need to call registerS3method in order to use it: cran.r-project.org/web/packages/knitr/vignettes/knit_print.htmlSophister
Thanks @ Starja for this vignette. The meta parameter from asis_output looks promising to setup js library, however I didn't figure out how to use it properly in order to answer my question.Saga
yes, I also find this argument poorly documented and couldn't really make sense of itSophister
S
3

The answer to my question has been given by @cderv :
https://github.com/rstudio/rmarkdown/issues/1877#issuecomment-679864674

The results = 'asis' is now more documented in https://bookdown.org/yihui/rmarkdown-cookbook/results-asis.html#results-asis . It is aimed at generating raw mardown content from a R chunk. Anything must result in a text output, and implicitly that means no knitr magic really happens for any R object in those chunk, because knitr does no adjustment when knit_printing the content (as it is juts text)

I think I would not use result = 'asis' to cat() a complex R object like an htmlwidget. You found a workaround but you may encounter other issues.

As this answer has been liked by @yihui, it gives a hint that cat + asis on htmlwidget should be used at one's own risk.

However, I'll personnaly continue to use the workarounds mentioned in the question, because as long as it works I find it very practical.

Thanks @atusi & @cderv for their valuable input.

Saga answered 29/8, 2020 at 6:57 Comment(0)
L
5

If you really need 'asis', then you add extra dependencies manually such as JavaScript and CSS. You can do it with knitr::knit_meta_add().

```{r, results='asis'}
library(purrr)
data.frame() %>%
  DT::datatable() %>%
  knitr::knit_print() %>%
  attr('knit_meta') %>%
  knitr::knit_meta_add() %>%
  invisible()

df_list <- list("cars" = mtcars, "flowers" = iris)
imap(df_list, ~{
      cat('## Subtab ',.y,'\n')
      cat('\n')
      cat(knitr::knit_print(DT::datatable(.x)))})
```
Largess answered 24/8, 2020 at 8:47 Comment(1)
Thanks @Largess for the knitr::knit_meta_add() suggestion. I think we're on the right way. However if I copy straight away this code in the example code I provided (see edit of my post), tabs aren't created properly. From your answer, the easiest working way seems DT:datatable(data.frame() in the previous non asis chunck to force initialization.Saga
L
3

You can output multiple datatables without asis. Just put the list of widgets into tagList()

```{r}
library(purrr)
list("cars" = mtcars, "flowers" = iris) %>%
  map(~DT::datatable(.x)) %>%
  htmltools::tagList()
```
Largess answered 24/8, 2020 at 1:27 Comment(1)
Thanks for your answer, this is correct in this case! However in two of the examples I sent, 'asis' is needed to be able to create sub tabs following a {.tabset} Markdown option. So the question relates specifically to 'asis'Saga
S
3

The answer to my question has been given by @cderv :
https://github.com/rstudio/rmarkdown/issues/1877#issuecomment-679864674

The results = 'asis' is now more documented in https://bookdown.org/yihui/rmarkdown-cookbook/results-asis.html#results-asis . It is aimed at generating raw mardown content from a R chunk. Anything must result in a text output, and implicitly that means no knitr magic really happens for any R object in those chunk, because knitr does no adjustment when knit_printing the content (as it is juts text)

I think I would not use result = 'asis' to cat() a complex R object like an htmlwidget. You found a workaround but you may encounter other issues.

As this answer has been liked by @yihui, it gives a hint that cat + asis on htmlwidget should be used at one's own risk.

However, I'll personnaly continue to use the workarounds mentioned in the question, because as long as it works I find it very practical.

Thanks @atusi & @cderv for their valuable input.

Saga answered 29/8, 2020 at 6:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.