Search code examples
rshinydatatabledownload

How to have a single download button for all datatables in R shiny webpage


I am working with a shiny app where it is desired to have a single downloadButton in the header of the application that downloads the data table present in the current/active page/tab.

Below is a simple app that has two data tables in page1 and one in page 2. Each data table has the csv , excel buttons on top of each data table.

Could these csv, excel buttons be removed and place a single downloadButton in a fixed position in the header bar that offers to download csv/excel options of the active table in the current page or tab.

The idea is to have a single fixed downloadButton for the entire app in the header bar. Any possible solutions within shiny to do this or if anyone has attempted this before.

library(shiny)
library(shinydashboard)

ui <- dashboardPage(
  dashboardHeader(title = "Header",
                  dropdownMenuOutput("updatedTimeOutput"),
                  dropdownMenu(type = "notifications", 
                               badgeStatus = "warning",
                               icon = icon("bullhorn", "fa-lg"),
                               notificationItem(icon = icon("bullhorn", "fa-1x"),
                                                status = "info",
                                                text = tags$span(
                                                  tags$b("Please notice!")
                                                )
                               ))),
  dashboardSidebar( sidebarMenu(id = "tabs",
                                menuItem("Page1", tabName = "page1"),
                                menuItem("Page2", tabName = "page2"))),
  dashboardBody(
    tabItems(
      tabItem(
        tabName = "page1",

      tabBox(id="tabs",
      tabPanel("tab1",
          column(12,
                 DT::dataTableOutput("table1")
                 )),
       
       tabPanel( "tab2",
          column(12,
                DT::dataTableOutput("table2")
                ))
       )
      )
      ,
      tabItem(
        tabName = "page2",
        fluidRow(
          column(12,
                 DT::dataTableOutput("table3")
          ))
      )
    )
    )
    )



server <- function(input, output) {
  
  output$table1 <- DT::renderDataTable({
    datatable( data = mtcars,
               options = DToptions,
               extensions = 'Buttons',
               rownames = TRUE,
               selection = 'none'
    )
  })
  
  output$table2 <- DT::renderDataTable({
    datatable( data = mtcars,
               options = DToptions,
               extensions = 'Buttons',
               rownames = TRUE,
               selection = 'none'
    )
  })
    
  output$table3 <- DT::renderDataTable({
    datatable( data = mtcars,
               options = DToptions,
               extensions = 'Buttons',
               rownames = TRUE,
               selection = 'none'
    )
  })
  
  
}

shinyApp(ui, server)

Solution

  • (a) If you only want "one downloadButton visible in the header common to all pages that downloads the table in the active page or tab", it needs firstly to know the active page and tab based on the page / tab IDs. (b) If you only need a single button to download all the tables, you can download them into a .xlsx file (see download data onto multiple sheets from shiny). (c)If you need a button for each tab, place the button in each tab and you can simply save table as .csv. Here is the code for situation (a).

    library(shiny)
    library(shinydashboard)
    library(DT)
    
    ui <- dashboardPage(
      dashboardHeader(title = "Header",
                      dropdownMenuOutput("updatedTimeOutput"),
                      dropdownMenu(type = "notifications", 
                                   badgeStatus = "warning",
                                   icon = icon("bullhorn", "fa-lg"),
                                   notificationItem(icon = icon("bullhorn", "fa-1x"),
                                                    status = "info",
                                                    text = tags$span(
                                                      tags$b("Please notice!")
                                                    )
                                   ))),
      dashboardSidebar( sidebarMenu(id = "pages", # use unique id for pages
                                    menuItem("Page1", tabName = "page1"),
                                    menuItem("Page2", tabName = "page2"))),
      dashboardBody(
        
        # Add download button 
        downloadButton('downloadData', 'Download Table',
                       style="font-weight:bold;"
        ),
        helpText(
          hr(style = "border-top: 1px solid #000000;"), 
        ),
        
        tabItems(
          tabItem(
            tabName = "page1",
    
             tabsetPanel(id="tabs",
                          
                   tabPanel("tab1",
    
                            column(12,
                                   DT::dataTableOutput("table1")
                            )),
                   
                   tabPanel( "tab2",
    
                             column(12,
                                    DT::dataTableOutput("table2")
                             ))
            )
          )
          ,
          tabItem(
            tabName = "page2",
            fluidRow(
              column(12,
                     DT::dataTableOutput("table3")
              ))
          )
        )
      )
    )
    
    
    
    server <- function(input, output) {
      
      # table1
      tbl1 <- mtcars[1:30, ] # tables 1, 2, 3 use different rows of mtcars to differentiate tables
      
      output$table1 <- DT::renderDataTable({
        datatable( tbl1,
                   #    options = DToptions, # no such object called "DToptions"
                   extensions = 'Buttons',
                   rownames = TRUE,
                   selection = 'none'
        )
      })
      
      
      # table2
      tbl2 <-  mtcars[5:45, ]
      
      output$table2 <- DT::renderDataTable({
        datatable( tbl2,
                   #    options = DToptions,
                   extensions = 'Buttons',
                   rownames = TRUE,
                   selection = 'none'
        )
      })
      
      # table3
      tbl3 <-  mtcars[11:35, ]
      
      output$table3 <- DT::renderDataTable({
        datatable( tbl3,
                   #    options = DToptions,
                   extensions = 'Buttons',
                   rownames = TRUE,
                   selection = 'none'
        )
      })
      
    
      page_name <- reactive({
        input$pages
      })
      
      # select table on the active page / tab
      selected_table <- reactive({
        if(page_name() == "page1"){
          tbl.list <- list("tab1" = tbl1, "tab2" = tbl2)
          select_tbl <- tbl.list[input$tabs]
        }else{
          select_tbl <- tbl3
        }
        return(select_tbl)
      })
      
      # download table
      output$downloadData <- downloadHandler(
        filename = function() {"table.csv"},
        content = function(file) {write.csv(selected_table(), file, row.names=TRUE)}   
      )    
    }
    
    shinyApp(ui, server)