如何在闪亮忙碌并显示加载文本时禁用所有操作按钮 [英] How can I disable all action buttons while shiny is busy and loading text is displayed

查看:70
本文介绍了如何在闪亮忙碌并显示加载文本时禁用所有操作按钮的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在闪亮的应用程序内部,我想在应用程序运行时禁用所有按钮。我有很多动作按钮,依赖项和一些renderui东西,因此我认为使用Shinyjs:disable(button)至关重要,并且超过40个以上的按钮非常不干净。

Inside a Shiny App I want to disable all buttons while the app is running. I have a lot of action buttons, dependencies and some renderui stuff, so that I think using shinyjs:disable(button) is crucial and very unclean over 40 and more buttons.

是否有一种简便的方法可以在闪亮的应用程序忙时禁用按钮(或同时禁用所有按钮/滑块),例如在加载状态下。

Is there an easy way to disable a button (or all buttons/sliders at once) while the shiny app is busy, like in the condition of the "loading.." element of my example app below?

还是还有另一种方法来禁止所有按钮被单击或在加载指示的长时间计算运行时使其不可见。文本?

or is there another way to disable all buttons from being clicked or make them invisible while long computations are running indicated by the "loading.." text?

在下面的示例中,我想在应用程序忙时禁用操作按钮(显示正在加载...文本)。我知道在此示例中,我可以使用Shinyjs,但在应用繁忙时,我希望使用整体解决方案。真的很欢迎任何帮助,我对html,css和java完全陌生,因此,如果有人知道解决方案,简短的解释将非常棒!

In my example below I want to disable the action button while the app is busy (the "loading.." text is shown). I know for this example I could use shinyjs but I would prefer an overall solution while the app is busy. Any help is really welcome, I am completely new to html,css and java stuff so if somebody knows a solution to this, a short explanation would be really great!

很多

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) 


推荐答案

我不熟悉执行您所描述的简单方法,但是,这当然并不意味着没有;)这是我认为可以满足您的要求并保持您的要求的一种解决方法代码相对干净,我们可以使用 reactiveValuesToList(input)来获取输入列表,然后编写一个禁用或启用所有输入的函数。通过根据属性对列表进行子设置,决定仅切换按钮输入。

I am not familiar with a simple way to do what you are describing, but of course that does not mean there is none ;) Here is a little workaround that I believe matches your requirements, and keeps your code relatively clean. We can use reactiveValuesToList(input) to get a list of our inputs, and then write a function that disables or enables them all. We can also decide to only toggle button inputs by subsetting the list based on attributes.

下面的工作示例,希望对您有所帮助!

Working example below, hope this helps!

< a href = https://i.stack.imgur.com/ea0A1.gif rel = nofollow noreferrer>

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)






替代解决方案

此解决方案使用自定义 JavaScript 根据Shiny是忙还是闲来启用/禁用所有输入。因此,只要Shiny忙,这将禁用您的输入。现在,我将脚本设置为禁用所有按钮,但是您可以通过在 document.getElementsByTagName()中添加更多选择来轻松扩展它。希望这更接近您的想法。

This solution uses custom JavaScript to enable/disable all inputs based on if Shiny is busy or idle. This will thus disable your inputs anytime Shiny is busy. I now set the script to disable all buttons, but you can easily extend it by adding more selections to document.getElementsByTagName(). Hope this comes closer to what you had in mind.

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)

script.js

script.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;
}
});

这篇关于如何在闪亮忙碌并显示加载文本时禁用所有操作按钮的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆