reactable icon indicating copy to clipboard operation
reactable copied to clipboard

Table not rendering when with CSV download button

Open GitHunter0 opened this issue 1 year ago • 6 comments

Hi folks, the table is not rendering when I add the CSV download button.

I'm trying this code:

library(shiny)
library(reactable)

n=1e4
df <- data.frame(
  id = 1:n,
  x = runif(n),
  name = sample(c("João", "Maria", "Cláudia", "Alice", "Mike",
                  "Emma", "Tom", "Sarah", "David", "Lily"), n, replace = TRUE),
  z = sample(1:100, n, replace = TRUE)
)

ui <- fluidPage(
  titlePanel("reactable example"),
  reactableOutput("table")
)

server <- function(input, output, session) {
  output$table <- renderReactable({
    
    htmltools::browsable(
      tagList(
        tags$button(
          tagList(fontawesome::fa("download"), "Download as CSV"),
          onclick="Reactable.downloadDataCSV('df-download-table', 'df.csv')"
        ),
    
        reactable(df, elementId = "df-download-table",
                  pagination = TRUE, 
                  height = 350,
                  defaultPageSize = 100,
                  showPageSizeOptions=TRUE,
                  pageSizeOptions = c(10, 50, 100, 1000),
                  highlight = TRUE, 
                  sortable = TRUE,
                  resizable = TRUE,
                  filterable = TRUE,
                  searchable = TRUE
        )
      )
    )
  })
}

shinyApp(ui, server)

And getting this empty page: image

Am I doing something wrong?

Thank you

R version 4.4.0 (2024-04-24 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 10 x64 (build 19045)

Matrix products: default

locale:
[1] LC_COLLATE=English_United States.utf8 
[2] LC_CTYPE=English_United States.utf8   
[3] LC_MONETARY=English_United States.utf8
[4] LC_NUMERIC=C                          
[5] LC_TIME=English_United States.utf8    

time zone: America/Sao_Paulo
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods  
[7] base     

other attached packages:
[1] reactable_0.4.4 shiny_1.8.1.1  

loaded via a namespace (and not attached):
 [1] config_0.3.2      sass_0.4.9        utf8_1.2.4       
 [4] generics_0.1.3    anytime_0.3.9     renv_1.0.7       
 [7] stringi_1.8.4     lattice_0.22-6    digest_0.6.35    
[10] magrittr_2.0.3    grid_4.4.0        shiny.i18n_0.3.0 
[13] fastmap_1.2.0     jsonlite_1.8.8    Matrix_1.7-0     
[16] DBI_1.2.3         promises_1.3.0    purrr_1.0.2      
[19] fansi_1.0.6       crosstalk_1.2.1   box_1.2.0        
[22] jquerylib_0.1.4   codetools_0.2-20  cli_3.6.2        
[25] rlang_1.1.4       bit64_4.0.5       cachem_1.1.0     
[28] reactR_0.5.0      yaml_2.3.8        tools_4.4.0      
[31] shinylogs_0.2.1   memoise_2.0.1     nanotime_0.3.7   
[34] pryr_0.1.6        dplyr_1.1.4       DT_0.33          
[37] httpuv_1.6.15     reticulate_1.37.0 vctrs_0.6.5      
[40] logger_0.3.0      R6_2.5.1          mime_0.12        
[43] png_0.1-8         zoo_1.8-12        lifecycle_1.0.4  
[46] stringr_1.5.1     pool_1.0.3        htmlwidgets_1.6.4
[49] fs_1.6.4          bit_4.0.5         usethis_2.2.3    
[52] fontawesome_0.5.2 pkgconfig_2.0.3   bslib_0.7.0      
[55] pillar_1.9.0      later_1.3.2       glue_1.7.0       
[58] data.table_1.15.4 Rcpp_1.0.12       tibble_3.2.1     
[61] tidyselect_1.2.1  rstudioapi_0.16.0 xtable_1.8-4     
[64] htmltools_0.5.8.1 compiler_4.4.0    mongolite_2.8.0  
[67] RcppCCTZ_0.2.12  

GitHunter0 avatar Jun 14 '24 20:06 GitHunter0

Hi, did you figure this out yet? If you're using RStudio here, it might be the bug with R 4.4.0 breaking the viewer in RStudio on Windows. Upgrading to R 4.4.1 fixed this for me. See https://github.com/rstudio/rstudio/issues/14603

glin avatar Jul 01 '24 03:07 glin

Thank you for the feedback, @glin .

Unfortunately not, I upgraded to R 4.4.1, updated all packages, tested in RStudio Viewer and in all external browsers, but the issue remains...

Unlike https://github.com/rstudio/rstudio/issues/14603 , the title reactable example is correctly displayed, just the table per se is blank when it is enclosed by htmltools::browsable().

What is your version of htmltools ?

Are you using Windows OS?

EDIT: Now I replicated the issue with R 4.3.1 too.

GitHunter0 avatar Jul 01 '24 05:07 GitHunter0

Sorry I didn't pay close attention and look at the app, just saw the session info and thought of the RStudio issue immediately. The problem is actually that renderReactable() must return a reactable() object only. If you want to add other UI elements to it, you'll have to do it around reactableOutput() instead. Here's a working example:

library(shiny)
library(reactable)

n=1e4
df <- data.frame(
  id = 1:n,
  x = runif(n),
  name = sample(c("João", "Maria", "Cláudia", "Alice", "Mike",
                  "Emma", "Tom", "Sarah", "David", "Lily"), n, replace = TRUE),
  z = sample(1:100, n, replace = TRUE)
)

ui <- fluidPage(
  titlePanel("reactable example"),
  tagList(
    tags$button(
      tagList(fontawesome::fa("download"), "Download as CSV"),
      onclick="Reactable.downloadDataCSV('table', 'df.csv')"
    ),
    reactableOutput("table")
  )
)

server <- function(input, output, session) {
  output$table <- renderReactable({
    reactable(df,
              pagination = TRUE, 
              height = 350,
              defaultPageSize = 100,
              showPageSizeOptions=TRUE,
              pageSizeOptions = c(10, 50, 100, 1000),
              highlight = TRUE, 
              sortable = TRUE,
              resizable = TRUE,
              filterable = TRUE,
              searchable = TRUE
    )
  })
}

shinyApp(ui, server)

Also, for Shiny outputs, the table ID for the JavaScript API is the Shiny output ID, so that would be table in this case.

We could probably use more examples for more complex Shiny apps like this. And also, it would be better if renderReactable() produced some kind of error when given an unexpected result, so that's another area of improvement.

glin avatar Jul 02 '24 01:07 glin

I understand @glin , the problem with this method is that you separate the download button from the table, so they are not rendered simultaneously.

For example, I have an app that I want to display the whole table only after I click in the button run. However, the download button will always be visible since it is in the UI part.

Of course you can add another reactive piece to hide the download button, however it adds unnecessary complexity to an app with many tables.

Is there another way to render the download button together with the table (as DT does)? htmltools::browsable(tagList(...)) (which I saw in reactable documentation) was a way to force that, right?

Thank you

GitHunter0 avatar Jul 02 '24 03:07 GitHunter0

You'll probably want renderUI({ ... }) instead then, with a condition on the run button for whether to return UI. Here's an example:

library(shiny)
library(reactable)

n=1e4
df <- data.frame(
  id = 1:n,
  x = runif(n),
  name = sample(c("João", "Maria", "Cláudia", "Alice", "Mike",
                  "Emma", "Tom", "Sarah", "David", "Lily"), n, replace = TRUE),
  z = sample(1:100, n, replace = TRUE)
)

ui <- fluidPage(
  titlePanel("reactable example"),
  uiOutput("table_ui")
)

server <- function(input, output, session) {
  output$table_ui <- renderUI({
    tagList(
      tags$button(
        tagList(fontawesome::fa("download"), "Download as CSV"),
        onclick="Reactable.downloadDataCSV('table', 'df.csv')"
      ),
      reactableOutput("table")
    )
  })

  output$table <- renderReactable({
    reactable(df,
              pagination = TRUE, 
              height = 350,
              defaultPageSize = 100,
              showPageSizeOptions=TRUE,
              pageSizeOptions = c(10, 50, 100, 1000),
              highlight = TRUE, 
              sortable = TRUE,
              resizable = TRUE,
              filterable = TRUE,
              searchable = TRUE
    )
  })
}

shinyApp(ui, server)

glin avatar Jul 03 '24 05:07 glin

Thank you, @glin . I still would prefer the download button being a merged built-in part of the table (and following its layout style) like DT. But since this workaround is working, feel free to close this issue.

GitHunter0 avatar Jul 05 '24 13:07 GitHunter0