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

Posted

技术标签:

【中文标题】闪亮的应用程序:禁用下载按钮【英文标题】:shiny app : disable downloadbutton 【发布时间】:2014-10-04 13:14:13 【问题描述】:

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

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

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

让我知道你的想法。

这是我的用户界面代码

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

【问题讨论】:

条件(准备下载)是否仅对服务器可见?如果您可以在ui.R 上检测到某些内容,您可以尝试将downloadButton 包装为conditionalPanel。如果条件不满足,您可以隐藏它。 或者,输入中除了下载按钮之外还有什么会触发数据处理的吗?因为似乎数据处理依赖于一些用户输入。如果你能提供更多细节,我可以给你一个例子。 outputData 是反应值吗? 你说得对,conditionalPanel 是解决此问题的最简单方法,我承认有时我倾向于使用此快捷方式。感觉不好,因为删除由于某些特殊条件而无法按下的按钮违反了良好界面设计的所有规则。我希望在 Shiny 中有一个conditionalDisablePanel。作为一种解决方法,我让按钮保持启用状态并显示一条错误消息来解释原因。 @DieterMenne,你总是可以编写一些 javascript 来实现类似conditionalDisablePanel 的东西。实际上,您可以使用 Javascript 显着增强您的 Shiny App。 @DieterMenne:受您的 conditionalDisabledPanel 想法的启发,这里有一个 R sn-p 正是这样做的 :) gist:condDisabledPanel.R 【参考方案1】:

根据您的评论:

是的,数据处理取决于用户输入。 USer 将上传一些文件并单击一个Action 按钮开始处理。下载按钮位于标签集中。

假设操作按钮名为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来处理自定义消息事件。


一个完整的例子是:

服务器.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 实现为&lt;a&gt; 标签而不是&lt;button&gt;,并且它绑定了click 事件。因此,为了完全禁用它,除了添加disabled 属性使其看起来被禁用之外,您还需要通过添加内联onclick 属性来覆盖其click 事件。否则用户仍可能不小心点击(看似已禁用)的下载按钮并触发下载。

【讨论】:

非常感谢!我会尽快尝试并告诉您结果。【参考方案2】:

只需添加另一个与 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")
  
))

【讨论】:

非常好。一个问题,不过。致电Sys.sleep(0) 的目的是什么? 哎呀,我显然是想在里面放一个数字。我把它改成了1。它只是一个显示时间流逝的占位符,就好像调用了一个数据处理函数 @DeanAttali,我知道现在问已经晚了,但是如果在调用 downloadHandler 时需要处理怎么办? parametersoutput$data_file 中传递给content 调用了一些函数,它的计算需要时间......关于这个的任何解决方案?

以上是关于闪亮的应用程序:禁用下载按钮的主要内容,如果未能解决你的问题,请参考以下文章

将数据导出到 SQL DB 时闪亮禁用操作按钮 x 秒

在闪亮的应用程序中取消选择列或编辑数据表时,下载按钮消失

如何根据带有闪亮元素的 R Markdown 文档中的条件禁用按钮?

使用响应式表达式启用/禁用按钮

r闪亮:按下按钮时eventReactive没有反应

从服务器端禁用/启用侧边栏