闪亮的应用:禁用下载按钮

shiny app : disable downloadbutton

本文关键字:下载 按钮 应用      更新时间:2023-09-26

我的闪亮的应用程序产生一些文件,用户可以下载。为此,我在ui中放置了下载按钮。但是,当页面启动时,在完成任何计算之前,没有任何东西可以下载。我想阻止用户下载空页面。

为此,我想在输出准备好之前禁用downloadButton。但我不知道该怎么做。我已经找到了禁用ActionButton的方法(如ShinyBS包和其他JS代码),但没有downloadButton。

现在,如果输出没有准备好,我使用validate()抛出错误。然而,当下载按钮被点击时,一个新的空白网页打开,其中有一个丑陋的错误信息。

让我知道你的想法。

这是我的ui代码
 downloadButton('download', 'Download Lasso component matrix')),

,这是我的服务器代码:

  output$download_matrix <- downloadHandler(
      filename = function() { 
      validate(
      need(is.null(outputData())==FALSE, "No data to download yet")
      )
      paste('combined_model_matrix', '.txt', sep='') },
    content = function(file) {
      write.csv(outputData()$combinedAdjMtr, file)
})

只是添加了另一个答案,它的工作方式与Xin的类似,但使用了一个本地支持启用/禁用按钮的包(shinyjs),而不必自己处理混乱的javascript。使用这个包,您可以简单地调用disable("download")enable("download")

这里有一个完整的例子,复制了Xin的答案,但使用了这个包

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")
  }
))

根据您的评论:

yes数据处理取决于用户输入。用户将上传一些文件,并单击action按钮开始处理。下载按钮在一个选项卡集中。

假设动作按钮命名为input$start_proc

服务器。接待员:

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
})

然后在ui。在R中,你可以编写一些javascript来处理自定义消息事件。


一个完整的例子是:

服务器。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.")
    )
  )
))

在本例中,通过等待5秒来伪造数据处理。然后下载按钮就准备好了。我还在消息中添加了一些"假"fileSize信息,以演示如何向用户发送额外的信息。

请注意,因为Shiny将actionButton实现为<a>标签而不是<button>,并且它将click事件绑定在其上。因此,为了完全禁用它,除了添加一个disabled属性使其看起来被禁用之外,还需要通过添加一个内联onclick属性来覆盖它的click事件。否则,用户仍然可能不小心点击(看似禁用的)下载按钮并触发下载。