How to disable download button in shiny until user uploads the data

shiny
#1

Hi Shiny experts,

The question seems similar here. But I found necessity to ask because of following reason:

  1. Not sure how much does shinyjs package cost
  2. It seems complicated for me to understand their code with js.

Could someone use the working code below and help me how to disable the download button until user upload an excel file or see the display

library(shiny)
library(magrittr) # Load magrittr for the piping operator %>%
library(DT)
library(readxl)
library(tidyselect)
library(writexl)
library(dplyr)
library(tidyr)
library(readxl)
library(stringr)

# Increase band width for shiny to handle bigger file 
options(shiny.maxRequestSize=30*1024^2) 

# Function to read all excel sheet necessary
read_excel_allsheets <- function(filename, tibble = FALSE) {
  sheets <- readxl::excel_sheets(filename)
  x <- lapply(sheets, function(X) readxl::read_excel(filename, sheet = X, col_names = T, skip = 5
                                                     ,col_types = "text"
  ))
  if(!tibble) x <- lapply(x, as.data.frame)
  names(x) <- sheets
  x
}

# Module UI to read content
mod_readUI <- function(id) {
  ns <- shiny::NS(id)
  shiny::tagList(
    fileInput(ns("file1"), h6("Choose xlsx file")
              ,accept=c(".xlsx"))
  )
}

# Module UI to display content
mod_displayUI <- function(id) {
  ns <- shiny::NS(id)
  shiny::tagList(
    DT::dataTableOutput(ns("contents"))
  )
}

# Module UI to download content
mod_downloadUI <- function(id) {
  ns <- shiny::NS(id)
  shiny::tagList(
    downloadButton(ns("downloadData"), "Download")
  )
}

# Server functions
mod_display <- function(input, output, session, file) {
  # In case want to alter the data to download
  # myfile = reactive({as.data.frame(file()[,1])})
  output$contents <- DT::renderDataTable({
    DT::datatable(file()
                  ,options = list(pageLength = 7,scrollX = TRUE))
  })
  
  reactive({
    file()
    # myfile()
  })
}

mod_read <- function(input, output, session){
  
  getData <- reactive({
    req(input$file1)
    inFile <- input$file1
    mysheets <- read_excel_allsheets(inFile$datapath)
    ppm <- mysheets$Download
    ppm
  })
  
  ### In ordert to send data as reactive 
  reactive({
    getData()
  })
}

mod_download <- function(input, output, session, displayData){
  
  output$downloadData <- downloadHandler(
    # browser(),
    filename = function() {
      paste("Updated file dated-", Sys.Date(), ".xlsx")
    },
    
    content = function(file) {
      write_xlsx(displayData(),file)
    }
  )
  
}

ui <- 
  
  shinydashboard::dashboardPage(
    skin = "yellow",
    # HEADER -----
    shinydashboard::dashboardHeader(
      title = "Modularizing App"
    ),
    # SIDEBAR -----
    shinydashboard::dashboardSidebar(
      shinydashboard::sidebarMenu(id = "menu",
                                  shinydashboard::menuItem('Example', tabName = 'example', icon = shiny::icon('file'))
                                  ) 
    ),
    # BODY -----
    shinydashboard::dashboardBody(
      shinydashboard::tabItems(
        shinydashboard::tabItem("example", mod_displayUI("bodymod"),mod_readUI("sidemod"),mod_downloadUI("downmod"))
      )
    )
  )

server <- function(input, output) {
  readFile <- shiny::callModule(mod_read, "sidemod")
  displayFile <- shiny::callModule(mod_display, "bodymod", file = readFile)
  shiny::callModule(mod_download, "downmod", displayFile)
  
}

shinyApp(ui,server)
0 Likes

#2

Here is a very simple application demonstrating enabling and disabling a button. The Make Plot button is initially disabled and it can be enabled or disabled with two other buttons. When the Make Plot button is enabled, clicking it generates a plot.

library(shiny)
library(shinyjs)

# Define UI for application that draws a histogram
ui <- fluidPage(
  useShinyjs(),
   # Application title
   titlePanel("Old Faithful Geyser Data"),
   
   sidebarLayout(
      sidebarPanel(
         disabled(actionButton("MakePlot", "Make Plot")),
         br(),
         actionButton("EnableButton", "Enable Button"
                      ),
         actionButton("DisableButton", "Disable Button"
                      )
      ),
      
      # Show a plot of the generated distribution
      mainPanel(
         plotOutput("distPlot")
      )
   )
)

server <- function(input, output) {
   
  observeEvent(input$MakePlot, {
     output$distPlot <- renderPlot({
       x    <- faithful[, 2] 
       hist(x, breaks = 30, col = 'darkgray', border = 'white')
     })
   })
   
   observeEvent(input$EnableButton, {
     enable("MakePlot")
   })
   
   observeEvent(input$DisableButton, {
     disable("MakePlot")
   })
}

# Run the application 
shinyApp(ui = ui, server = server)
1 Like

#3

Thanks for quick and simplified solution.

Can we use shinyjs for commercial purpose ?Because as I mentioned in the question, it needs further approval to use it

0 Likes

#4

A solution that doesn't require shinyjs is to use shiny::renderUI to only show the button if data is loaded, otherwise show nothing. In your UI replace mod_downloadUI("downmod") with uiOutput("downmod_ui") then in your server add:

output$downmod_ui <- renderUI({
  req(readFile()) # requires readfile to be non-null before running code below
  mod_downloadUI("downmod")
})
0 Likes