【问题标题】:Enable Action Button if Input has changed如果输入已更改,则启用操作按钮
【发布时间】:2021-03-23 08:37:03
【问题描述】:

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

除了最后一点,动作按钮的启用之外,大多数这种期望的行为都可以正常工作。这是我的服务器功能(操作按钮名为“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)
        })
    }

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

作为第二个问题,您建议封装这个按钮/禁用/启用模式,我计划在多个闪亮模块上使用它。如果我能专注于主要代码,即binsoutput$figure &lt;- ...,那就太好了。

感谢任何提示!

为了重现性,这里是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)

【问题讨论】:

    标签: r shiny shinyjs


    【解决方案1】:

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

    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 循环往往不适用于闪亮(不幸的是,我不知道为什么)。有几次在使用循环时启用输入不起作用,但使用lapply 我没有任何问题。

    【讨论】:

    • 这完全有道理。非常感谢。
    猜你喜欢
    • 2018-09-02
    • 1970-01-01
    • 2014-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-25
    相关资源
    最近更新 更多