r - 如果输入已更改,则启用操作按钮

标签 r shiny shinyjs

我的应用程序应遵循以下逻辑:如果按下操作按钮,则所有输入都将被禁用并执行长时间计算。当计算完成并绘制其结果时,除操作按钮之外的所有输入将再次启用。如果用户决定更改一项输入,操作按钮就会启用。

除了最后一点(即启用操作按钮)之外,大多数所需的行为都有效。这是我的服务器功能(操作按钮名为“go”):

server <- function(input, output, session) {
        allinputIds <- reactive(names(input))
                
        shiny::observeEvent(input$go, {
            for (id in allinputIds()) shinyjs::disable(id)  
        })
        
        # ==> here is some trouble: not working
        shiny::observeEvent(allinputIds(), shinyjs::enable("go"))
    
        # from here starts the real work
        bins <- shiny::eventReactive(input$go, {
            x <- faithful$waiting
            Sys.sleep(1.5)
            seq(min(x), max(x), length.out = input$bins + 1)
        })

        output$figure <- shiny::renderPlot({
            x <- faithful$waiting 
            hist(
                x, breaks = bins(), col = "#75AADB", border = "white",
                xlab = "Waiting time to next eruption (in mins)",
                main = "Histogram of waiting times"
            )
            for (id in setdiff(allinputIds(), "go")) shinyjs::enable(id)
        })
    }

我如何观察到任何输入已更改?而不是allinputIds()在标记为“==>”的行之后,我尝试了 input但这都不起作用。

作为第二个问题,您建议如何封装此按钮/禁用/启用模式,我计划在多个 Shiny 模块上使用该模式。如果我能专注于主要代码,即bins,那就太好了和output$figure <- ... .

任何提示表示赞赏!

为了重现性,这里是 ui 函数:

ui <- shiny::tagList(
    shinyjs::useShinyjs(), 
    shiny::navbarPage(title="Test 2",
        tabPanel(title="Old Faithful",
        shiny::sidebarLayout(
            shiny::sidebarPanel(
                    shiny::sliderInput(
                        inputId = "bins",
                        label = "Number of bins:",
                        min = 1,
                        max = 50,
                        value = 30
                    )
                ),
                shiny::mainPanel(
                    shiny::actionButton("go", "Update"),
                    shinycssloaders::withSpinner(plotOutput(outputId="figure")),
                    shiny::h4(shiny::textOutput("msg"))
                )
            )
        )
    )
)

shiny::shinyApp(ui, server)

最佳答案

问题是,在 shiny::observeEvent(allinputIds(),shinyjs::enable("go")) 中,您只需检查输入 id 的名称/数量是否发生变化 - 它们不会发生变化t。您实际上需要检查任何输入的值(除了操作按钮之外)是否已更改。因此,您可以将所有输入直接放入观察中,例如 c(input$bins, input$...) 或进行额外的 react 来检查值并调用此 react 。

library(shiny)

server <- function(input, output, session) {
  allinputIds <- reactive(names(input))
  
  changingInputValues <- reactive({
    checkIds <- setdiff(names(input), "go")
    lapply(checkIds, function(x) input[[x]])
  })
  
  observeEvent(input$go, {
    lapply(allinputIds(), shinyjs::disable)  
  })
  
  # ==> here is some trouble: not working
  observeEvent(changingInputValues(), shinyjs::enable("go"))
  
  # from here starts the real work
  bins <- eventReactive(input$go, {
    x <- faithful$waiting
    Sys.sleep(1.5)
    seq(min(x), max(x), length.out = input$bins + 1)
  })
  
  output$figure <- renderPlot({
    x <- faithful$waiting 
    hist(
      x, breaks = bins(), col = "#75AADB", border = "white",
      xlab = "Waiting time to next eruption (in mins)",
      main = "Histogram of waiting times"
    )
    
    lapply(setdiff(allinputIds(), "go"), shinyjs::enable)
  })
}

ui <- tagList(
  shinyjs::useShinyjs(), 
  navbarPage(title="Test 2",
                    tabPanel(title="Old Faithful",
                             sidebarLayout(
                               sidebarPanel(
                                 sliderInput(
                                   inputId = "bins",
                                   label = "Number of bins:",
                                   min = 1,
                                   max = 50,
                                   value = 30
                                 )
                               ),
                               mainPanel(
                                 actionButton("go", "Update"),
                                 shinycssloaders::withSpinner(plotOutput(outputId="figure")),
                                 h4(textOutput("msg"))
                               )
                             )
                    )
  )
)

shinyApp(ui, server)

请注意,我已将 for 循环更改为 lapply,因为 for 循环往往不适用于 Shiny (不幸的是,我不知道为什么)。有几次使用循环时启用输入不起作用,但使用 lapply 时我没有遇到任何问题。

关于r - 如果输入已更改,则启用操作按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65259650/

相关文章:

javascript - Shiny - 动态生成的输入

r - 在R Shiny中显示/隐藏整个框元素

r - 如何在r中仅标记tmap中的一个点?

r -\SweaveInput{} 错误消息声称存在的文件不存在

r - 如何访问作为 RMarkdown 文档中的参数传递的文件中的数据?

r - Shiny 无法在 RStudio 的浏览器中打开

根据存在层次结构的另一列删除一列中的重复项

r - plot.lm() 如何确定残差与拟合图的异常值?

r - 避免依赖于更新的 slider 值的计算的双重执行

css - 在 Shiny 中更改选择器输入的颜色