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

Javascript 闪亮应用:禁用下载按钮,javascript,r,shiny,shinyjs,Javascript,R,Shiny,Shinyjs,我的闪亮应用程序生成一些用户可以下载的文件。为此,我在用户界面中设置了downloadbutton。但是,当页面启动时,在进行任何计算之前,没有任何内容可供下载。我想阻止用户下载空页 为此,我想在输出准备就绪之前禁用downloadButton。但我不知道怎么做。我已经找到了禁用ActionButton的方法(比如ShinyBS包和其他JS代码),但对于downloadButton没有任何方法 现在,如果输出没有准备好,我使用validate()抛出错误。但是,当单击downloadButton

我的闪亮应用程序生成一些用户可以下载的文件。为此,我在用户界面中设置了downloadbutton。但是,当页面启动时,在进行任何计算之前,没有任何内容可供下载。我想阻止用户下载空页

为此,我想在输出准备就绪之前禁用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)
})
output$download\u matrix根据您的评论:

是,数据处理取决于用户输入。用户将上载一些文件,然后单击操作按钮开始处理。“下载”按钮位于选项卡集中

假设操作按钮名为
input$start\u proc

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


一个完整的例子是:

服务器.R
库(闪亮)
fakeDataProcessing(0){
伪造数据处理(5)
#通知浏览器数据已准备好下载
会话$sendCustomMessage(“下载准备就绪”,列表(fileSize=floor(runif(1)*10000)))
}
})

output$data_file只需添加另一个答案,该答案的工作方式与Xin的答案类似,但使用一个本机支持启用/禁用按钮的包(),而不必自己处理混乱的javascript。使用此软件包,您只需调用
禁用(“下载”)
启用(“下载”)

下面是一个完整的示例,它复制了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")
  }
))
库(闪亮)
图书馆(shinyjs)
runApp(shinyApp)(
ui=fluidPage(
#需要调用useShinyjs()才能在服务器中使用其函数
shinyjs::useShinyjs(),
操作按钮(“启动程序”,“单击以开始处理数据”),
下载按钮(“数据文件”)
),
服务器=功能(输入、输出){
观察({
如果(输入$start\u proc>0){
系统睡眠(1)
#启用下载按钮
shinyjs::enable(“数据文件”)
#更改下载按钮的html
shinyjs::html(“数据文件”,
斯普林特
下载(文件大小:%s)”,
圆形(runif(1,1,10000))
)
)
}
})

输出$data_文件为条件(准备下载)仅对服务器可见?如果您可以在
ui.R
上检测到某些内容,您可以尝试使用
条件面板
包装
下载按钮
。如果条件不满足,您可以将其隐藏。或者,输入中是否有除下载按钮以外的任何其他内容会触发数据处理?因为数据处理似乎取决于一些用户输入。如果您能提供更多的细节,我可以给您举个例子。
outputData
是一个被动值吗?您是对的,a
conditionalPanel
是解决这个问题的最简单的方法,我承认我有时倾向于使用这个快捷方式。带着不好的感觉,b因为删除由于某些特殊条件未满足而无法按下的按钮违反了良好界面设计的所有规则。我希望在Shining中有一个
conditionalDisablePanel
。作为一种解决方法,我将该按钮保持启用状态,并显示一条错误消息,解释原因。@Dietermene,您始终可以在im中编写一些Javascriptplement类似于
conditionalDisablePanel
。实际上,你可以用Javascript极大地增强你闪亮的应用程序。@DieterMane:受你的
conditionalDisablePanel
想法的启发,这里有一个R片段正是这样做的:)非常感谢!我将很快尝试并告诉您结果。非常好。不过有一个问题。调用
Sys.sleep(0)有什么作用
?哎呀,我显然是想在里面放一个数字。我把它改成了
1
。它只是一个占位符,表示时间在流逝,就好像一个数据处理功能正在运行一样called@DeanAttali,我知道现在提问已经晚了,但如果调用
downloadHandler
ie.
parameters
传递给
content在
输出$data\u文件中
调用一些函数,它的计算需要时间…有什么解决方案吗?
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)
       }
  )
})
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.")
    )
  )
))
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")
  }
))