如何在闪亮忙且显示加载文本时禁用所有操作按钮

JmO*_*JmO 2 html css r shiny

在 Shiny 应用程序中,我想在应用程序运行时禁用所有按钮。我有很多动作按钮、依赖项和一些 renderui 的东西,所以我认为使用 Shinyjs:disable(button) 是至关重要的,而且超过 40 个和更多的按钮非常不干净。

当闪亮的应用程序很忙时,是否有一种简单的方法可以禁用按钮(或同时禁用所有按钮/滑块),例如在我下面示例应用程序的“正在加载..”元素的情况下?

或者是否有另一种方法可以在“正在加载..”文本指示的长时间计算运行时禁用所有按钮被单击或使它们不可见?

在下面的示例中,我想在应用程序繁忙时禁用操作按钮(显示“正在加载..”文本)。我知道对于这个例子,我可以使用 Shinyjs,但我更喜欢在应用程序繁忙时使用整体解决方案。任何帮助都非常受欢迎,我对 html、css 和 java 的东西完全陌生,所以如果有人知道解决方案,简短的解释会非常棒!

提前谢谢了!

library(shiny)


server <- function(input, output) {
  output$moreControls <- renderUI({if(input$obs!=10001) actionButton("button", "OK!")})
  observeEvent(input$button, {
  output$distPlot <- renderPlot({
    Sys.sleep(5)
    hist(rnorm(isolate(input$obs)), col = 'darkgray', border = 'white')
  })})
}

ui <- fluidPage(tags$head(tags$style(type="text/css", "
                                                                    #loadmessage {
                                     position: fixed;
                                     top: 95%;
                                     left: 0px;
                                     width: 100%;
                                     padding: 5px 0px 5px 0px;
                                     text-align: center;
                                     font-weight: bold;
                                     font-size: 100%;
                                     color: #000000;
                                     background-color: #CCFF66;
                                     z-index: 105;
                                     }
                                     ")),
                conditionalPanel(condition="$('html').hasClass('shiny-busy')",
                                 tags$div("Loading...",id="loadmessage")),
  sidebarLayout( sidebarPanel(

    sliderInput("obs", "Number of observations:", min = 10000, max = 100000, value = 10001,step=1000),
   uiOutput("moreControls")

    ),
    mainPanel(plotOutput("distPlot"))
  )
)

shinyApp(ui = ui, server = server) 
Run Code Online (Sandbox Code Playgroud)

Flo*_*ian 6

我不熟悉执行您所描述的操作的简单方法,但当然这并不意味着没有 ;) 这是我认为符合您的要求并保持您的代码相对干净的一些解决方法。我们可以使用reactiveValuesToList(input)获取我们的输入列表,然后编写一个函数来禁用或启用它们。我们还可以决定button通过基于属性对列表进行子集化来仅切换输入。

下面的工作示例,希望这会有所帮助!


在此处输入图片说明


library(shiny)
library(shinyjs)

ui <- fluidPage(
  h3('Disable all inputs while running'),
  actionButton('btn_all_inputs','Run long process'),
  h3('Disable only buttons while running'),
  actionButton('btn_only_buttons','Run long process'),
  hr(),
  h3('Inputs'),
  textInput('text1', 'Text1',"my text:"),
  actionButton('btn1','Button 1'),
  actionButton('btn2','Button 2'),
  actionButton('btn3','Button 3'),
  sliderInput('slid3','Slider 1',min=0,max=1,value=0.5),
  useShinyjs()
)


server <- function(input, output, session){

  # Function to toggle input elements. 
  # input_list: List of inputs, reactiveValuesToList(input)
  # enable_inputs: Enable or disable inputs?
  # Only buttons: Toggle all inputs, or only buttons?
  toggle_inputs <- function(input_list,enable_inputs=T,only_buttons=FALSE)
  {
    # Subset if only_buttons is TRUE.
    if(only_buttons){
      buttons <- which(sapply(input_list,function(x) {any(grepl('Button',attr(x,"class")))}))
      input_list = input_list[buttons]
    }

    # Toggle elements
    for(x in names(input_list))
      if(enable_inputs){
        shinyjs::enable(x)} else {
          shinyjs::disable(x) }
  }

  observeEvent(input$btn_all_inputs,{
    input_list <- reactiveValuesToList(input)
    toggle_inputs(input_list,F,F)
    Sys.sleep(5)
    toggle_inputs(input_list,T,F)
  })

  observeEvent(input$btn_only_buttons,{
    input_list <- reactiveValuesToList(input)
    toggle_inputs(input_list,F,T)
    Sys.sleep(5)
    toggle_inputs(input_list,T,T)
  })
}

shinyApp(ui = ui, server = server)
Run Code Online (Sandbox Code Playgroud)

替代方案

该解决方案使用自定义JavaScript来根据 Shiny 是忙还是闲来启用/禁用所有输入。因此,这将在 Shiny 忙碌时禁用您的输入。我现在将脚本设置为禁用所有按钮,但您可以通过向document.getElementsByTagName(). 希望这更接近你的想法。

library(shiny)

ui <- fluidPage(
  h3('Disable buttons while running'),
  actionButton('btn_run','Run long process'),
  hr(),
  h3('Inputs'),
  textInput('text1', 'Text1',"my text:"),
  actionButton('btn1','Button 1'),
  sliderInput('slid3','Slider 1',min=0,max=1,value=0.5),
  includeScript('script.js')
)

server <- function(input, output, session){

  observeEvent(input$btn_run,{
    Sys.sleep(5)
  })
}

shinyApp(ui = ui, server = server)
Run Code Online (Sandbox Code Playgroud)

脚本.js

$(document).on("shiny:busy", function() {
  var inputs = document.getElementsByTagName("button");
  console.log(inputs);
for (var i = 0; i < inputs.length; i++) {
inputs[i].disabled = true;
}
});

$(document).on("shiny:idle", function() {
  var inputs = document.getElementsByTagName("button");
  console.log(inputs);
for (var i = 0; i < inputs.length; i++) {
inputs[i].disabled = false;
}
});
Run Code Online (Sandbox Code Playgroud)