首页 文章

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

提问于
浏览
7

我的闪亮应用程序生成一些用户可以下载的文件 . 为此,我已将下载按钮放在ui中 . 但是,当页面启动时,在完成任何计算之前,没有任何内容可供下载 . 我想阻止用户下载空白页面 .

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

现在,如果输出没有准备好,我使用validate()来抛出错误 . 但是,当单击downloadButton时,会打开一个新的空网页,其中包含一条很难看的错误信息 .

让我知道你的想法 .

这是我的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)
})

2 回答

  • 13

    根据您的评论:

    是数据处理取决于用户输入 . USer将上传一些文件并单击anAction按钮开始处理 . 下载按钮位于选项卡集中 .

    假设操作按钮名为 input$start_proc .

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

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


    一个完整的例子是:

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

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

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

  • 9

    只需添加另一个与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 text of the download button
            shinyjs::text("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")
      }
    ))
    

相关问题