shiny app : disable downloadbutton

后端 未结 2 1826
花落未央
花落未央 2020-12-31 16:37

My shiny app produces some files that user can download. I have put downloadbutton in the ui for this purpose. However, when the page launches and before any calculation is

相关标签:
2条回答
  • 2020-12-31 16:51

    Just adding another answer that works in a similar fashion to the one by Xin, but using a package (shinyjs) that natively supports enabling/disabling buttons, rather than having to deal with the messy javascript yourself. Using this package, you can simply call disable("download") or enable("download").

    Here's a full example replicating the answer by Xin but with this package

    library(shiny)
    library(shinyjs)
    
    runApp(shinyApp(
      ui = fluidPage(
        # need to make a call to useShinyjs() in order to use its functions in server
        shinyjs::useShinyjs(),  
        actionButton("start_proc", "Click to start processing data"),
        downloadButton("data_file")
      ),
      server = function(input, output) {
        observe({
          if (input$start_proc > 0) {
            Sys.sleep(1)
            # enable the download button
            shinyjs::enable("data_file")
            # change the html of the download button
            shinyjs::html("data_file",
                          sprintf("<i class='fa fa-download'></i>
                                  Download (file size: %s)",
                                  round(runif(1, 1, 10000))
                          )
            )
          }
        })
    
        output$data_file <- downloadHandler(
          filename = function() {
            paste('data-', Sys.Date(), '.csv', sep='')
          },
          content = function(file) {
            write.csv(data.frame(x=runif(5), y=rnorm(5)), file)
          }
        )
    
        # disable the downdload button on page load
        shinyjs::disable("data_file")
      }
    ))
    
    0 讨论(0)
  • 2020-12-31 16:52

    Based on your comment:

    yes data processing depends on the user input. USer will upload some files and click anAction button to start the processing. The download button is in a tab set.

    Let's say the action button is named input$start_proc.

    In server.R:

    shinyServer(function(input, output, session) {
       #... other code
       observe({
           if (input$start_proc > 0) {
               # crunch data...
               # when data is ready:
               session$sendCustomMessage("download_ready", list(...))
               # you can put extra information you want to send to the client 
               # in the ... part.
           } 
       })
       #... other code
    })
    

    Then in ui.R, you can write some javascript to handler the custom message event.


    A full example is:

    server.R

    library(shiny)
    
    fakeDataProcessing <- function(duration) {
      # does nothing but sleep for "duration" seconds while
      # pretending some background task is going on...
      Sys.sleep(duration)
    }
    
    shinyServer(function(input, output, session) {
    
      observe({
        if (input$start_proc > 0) {
          fakeDataProcessing(5)
          # notify the browser that the data is ready to download
          session$sendCustomMessage("download_ready", list(fileSize=floor(runif(1) * 10000)))
        }
      })
    
      output$data_file <- downloadHandler(
           filename = function() {
             paste('data-', Sys.Date(), '.csv', sep='')
           },
           content = function(file) {
             write.csv(data.frame(x=runif(5), y=rnorm(5)), file)
           }
      )
    })
    

    ui.R

    library(shiny)
    
    shinyUI(fluidPage(
      singleton(tags$head(HTML(
    '
      <script type="text/javascript">
        $(document).ready(function() {
          // disable download at startup. data_file is the id of the downloadButton
          $("#data_file").attr("disabled", "true").attr("onclick", "return false;");
    
          Shiny.addCustomMessageHandler("download_ready", function(message) {
            $("#data_file").removeAttr("disabled").removeAttr("onclick").html(
              "<i class=\\"fa fa-download\\"></i>Download (file size: " + message.fileSize + ")");
          });
        })
      </script>
    '
    ))),
      tabsetPanel(
        tabPanel('Data download example',
          actionButton("start_proc", h5("Click to start processing data")),
          hr(),
    
          downloadButton("data_file"),
          helpText("Download will be available once the processing is completed.")
        )
      )
    ))
    

    In the example the data processing is faked by waiting for 5 seconds. Then the download button will be ready. I also added some "fake" fileSize information in the message to demonstrate that how you can send extra information to the user.

    Note that because Shiny implements actionButton as <a> tag instead of <button>, and it binds click event on it. Therefore, in order to fully disable it, in addition to add a disabled attribute to make it appear to be disabled, you also need to override its click event by adding an inline onclick attribute. Otherwise the user can still accidentally click the (seemingly disabled) download button and triggers the download.

    0 讨论(0)
提交回复
热议问题