【问题标题】:Reactive input in RShiny reacts too quickly (without using a button)RShiny 中的反应式输入反应太快(不使用按钮)
【发布时间】:2021-01-06 23:56:42
【问题描述】:

如何让 Shiny 稍等片刻让用户输入他们的邮政编码(不使用按钮)。我面临的问题是,如果用户输入邮政编码的速度不够快,它会很快跳转到错误。 编辑:

  • 我在这个应用程序中有其他用户输入,但我在这个问题中对其进行了简化。我希望所有其他输入都能立即做出反应,因为它们是单选按钮。我认为按“返回”仍然会做与按钮相同的事情,这不是我想要的。我正在考虑仅将“Sys.sleep()”用于邮政编码输入,而不用于其他输入。这可能吗?
library(shiny)

shinyApp(ui <- fluidPage(sidebarPanel(
  "",
  textInput("zipcode", label = "Enter your zipcode.", value = 98125)
  
)) ,


server <- function(input, output, session) {
  observeEvent(input$zipcode, {
    #limits zipcode input to 5 numbers only
    if (nchar(input$zipcode) != 5)
    {
      updateTextInput(session, 'zipcode', value = 98125)
      showModal(
        modalDialog(
          title = "Error!",
          "Only 5-character entries are permitted.",
          easyClose = TRUE
        )
      )
    }
    if (is.na(as.numeric(input$zipcode)))
    {
      showModal(
        modalDialog(
          title = "Error!",
          "Only numeric values are allowed. Please try again.",
          easyClose = TRUE
        )
      )
    }
  })
})

【问题讨论】:

  • 一种简单的方法是添加一个他们在输入邮政编码后会单击的按钮。这行得通吗?
  • 我不想添加按钮 - 有没有办法解决这个问题?
  • 这会是一次愉快的 UI 体验吗?另一种方法是将req(nchar(input$zipcode) == 5) 放在所有依赖于邮政编码的反应中。您还可以使用 validate(need(nchar(input$zipcode) == 5, message = "Only 5-character zip entries are permitted.")) 在需要 zip 的输出位置给出错误。
  • @youtube input$zipcode 将是一个字符串,因此前导零仍将具有 nchar(input$zipcode) == 5。您可能需要在reqvalidate(need()) 中使用条件nchar(input$zipcode) == 5 &amp; !is.na(as.numeric(input$zipcode))。如果input$zipcode在很多地方使用,你可以使用clean_zip &lt;- reactive(validate(need(nchar(input$zipcode) == 5 &amp; !is.na(as.numeric(input$zipcode))), message = "Only 5-digit zip allowed."); input$zipcode),然后在任何你使用它的地方,你只需要在顶部放一个req(clean_zip())
  • 无论您使用哪种方法,我建议您简化事情并使用&amp; 将两个条件合并为一个测试。一条关于 5 位数拉链的错误消息就足够了。

标签: r shiny shiny-server shinyapps shiny-reactivity


【解决方案1】:

你可以使用debounce:

这让您可以忽略一个非常“健谈”的反应式表达式,直到它变得空闲,这在中间值与最终值无关紧要时很有用

你不需要Sys.sleep,它会在触发响应之前等待millis 毫秒:

library(shiny)

shinyApp(
  ui <- fluidPage( 
    sidebarPanel("", textInput("zipcode", label="Enter your zipcode.", value = 98125)
                 
    )  ) , 
  
  
  server <- function(input, output, session) {
    zipcode <- reactive(input$zipcode)
    zipcode_d <- debounce(zipcode, millis = 2000)
    observeEvent(zipcode_d(),{     #limits zipcode input to 5 numbers only
      if(nchar(zipcode_d())!=5)
      {
        updateTextInput(session,'zipcode',value=98125)
        showModal(modalDialog(
          title = "Error!",
          "Only 5-character entries are permitted.",
          easyClose = TRUE
        ))
      }
      if(is.na(as.numeric(zipcode_d())))
      {
        showModal(modalDialog(
          title = "Error!",
          "Only numeric values are allowed. Please try again.",
          easyClose = TRUE
        ))
      }
    }
    )
  })

【讨论】:

    【解决方案2】:

    添加了 JS 代码,input$keyPressed 会在任意位置按下“Return”键时接收一个随机数。

    library(shiny)
    
    js <- '
    $(document).on("keyup", function(e) {
      if(e.keyCode == 13){
        Shiny.onInputChange("keyPressed", Math.random());
      }
    });
    '
    
    shinyApp(ui <- fluidPage(tags$script(js),
                             sidebarPanel(
                               "",
                               textInput("zipcode", label = "Enter your zipcode.", value = 98125),
                               textOutput("zip")
                             )) ,
             
             server <- function(input, output, session) {
               observeEvent(input[["keyPressed"]], {
                 #limits zipcode input to 5 numbers only
                 if (nchar(input$zipcode) != 5)
                 {
                   updateTextInput(session, 'zipcode', value = 98125)
                   showModal(
                     modalDialog(
                       title = "Error!",
                       "Only 5-character entries are permitted.",
                       easyClose = TRUE
                     )
                   )
                 }
                 if (is.na(as.numeric(input$zipcode)))
                 {
                   showModal(
                     modalDialog(
                       title = "Error!",
                       "Only numeric values are allowed. Please try again.",
                       easyClose = TRUE
                     )
                   )
                 }
                 output$zip <- renderText(input$zipcode)
               })
             })
    

    链接到:Shiny Responds to Enter

    【讨论】:

    • 感谢您的想法!我在这个应用程序中有其他用户输入,但我在这个问题中对其进行了简化。我希望所有其他输入都能立即做出反应,因为它们是单选按钮。我认为按“返回”仍然会做与按钮相同的事情,这不是我想要的。我正在考虑仅将“Sys.sleep()”用于邮政编码输入,而不用于其他输入。这可能吗?
    • 那么@Waldi 解决方案可能会更好。但是要小心对用户施加这样的压力。告诉他们他们还需要多少时间来提供输入可能是个好主意。
    猜你喜欢
    • 1970-01-01
    • 2018-10-22
    • 2019-06-08
    • 2017-11-13
    • 2021-10-21
    • 1970-01-01
    • 1970-01-01
    • 2020-05-27
    • 2020-12-20
    相关资源
    最近更新 更多