0

I would like to render Shiny tabs (and other Shiny features) within an Rmarkdown document. Specifically, I'd like to display a table in each tab, generated with a loop.

We can add {.tabset} tag after a header and subsequent lower level headers will be separate tabs. I tried to make use of this by using cat() and the header level and a unique name at each loop for the tab name. That creates the tabs fine. Also, a table is created within each tab when I call the function with arguments separately.

However, when looping through the function, the tables are not being generated on each tab. In the final tab is output <shiny.render.function> for each loop.

I know if I was generating a table in Rmarkdown without Shiny, I'd print each table within each loop. However, there's no similar function for printing rendered Shiny objects.

---
output: html_document
runtime: shiny
---

## Tables Work {.tabset}

{r works, results='asis'}
# Function to generate a numbered tab and table within that tab
tbl_display_func <- function(tab_number, df){
  cat('### Results', tab_number,' \n\n')
    DT::renderDataTable({
      DT::datatable(
        head(df)
        )
    })
}

# Works fine to call the function separately
tbl_display_func(1, cars)
tbl_display_func(2, iris)

working_tabs_and_tables

Tables Don't Work {.tabset}

However, when I loop through the function, tables do not display.

{r do-not-work, results='asis'}
# Does not work here. Generates tabs, then list of <shiny.render.function> in tab 2
purrr::map2(
  .x = list(1,2),
  .y = list(cars, iris),
  .f = tbl_display_func
) 

I tried to create the tables as renderTableOutput output, as I might if creating multiple widgets just in shiny, and then calling those within a function, but this didn't help

Tables Don't Work {.tabset}

{r generate-tables-then-print, results='asis'}
# Function just to generate table
tbl_func <- function(df){
    DT::renderDataTable({
      DT::datatable(
        head(df)
        )
    })
}

# Store rendered table as output
tbl_func_output <- purrr::map(
  .x = list(cars, iris),
  .f = tbl_func
)

# Loop through each tab and table
display_func <- function(tab_number){
  cat('### Results', tab_number,' \n\n')
  tbl_func_output[[tab_number]]
}

    purrr::map(
      .x = 1:2,
      .f = display_func
    )

How might I loop through and create a table at each tab?

1 Answer 1

1

You need to do this

---
output: html_document
runtime: shiny
---


```{r}
do.call(tabsetPanel,
    mapply(y = list(cars, iris), x = list(1,2), function(x, y) {
        tabPanel(
            paste0("Results", x),  DT::renderDataTable({DT::datatable(head(y))})
        )
    }, SIMPLIFY = FALSE)
)
```

return of purrr::map2 is a list, not shiny.tag object. I don't think there is a way to have .tabset work with cat and DT::datatable together. You would choose only flexdashboard or shiny. Here I used shiny syntax.

enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, very good! I was able to use purrr::map2 working with your do.call(tabset... method. I did find also that we can use cat(knit_print(DT::datatable(head(df)))) by calling DT::datatable(matrix()) in an earlier chunk to print from within the loop (github.com/rstudio/DT/issues/67)
good to know the knit_print option

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.