youtube
youtube

Reputation: 504

Reactive input in RShiny reacts too quickly (without using a button)

How do I make it so that Shiny waits a little bit for the user to input their zip code (without using a button). The problem I'm facing is that it will quickly jump to the error if the user isn't fast enough at inputting their zip code. Edit:

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
        )
      )
    }
  })
})

Upvotes: 2

Views: 476

Answers (2)

Waldi
Waldi

Reputation: 41240

You could use debounce:

This lets you ignore a very "chatty" reactive expression until it becomes idle, which is useful when the intermediate values don't matter as much as the final value

You don't need Sys.sleep, it will wait millis milliseconds before triggering the reactives :

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
        ))
      }
    }
    )
  })

Upvotes: 2

polkas
polkas

Reputation: 4184

JS code added, input$keyPressed which receives a random number when the "Return" key is pressed anywhere.

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)
           })
         })

linked to: Shiny Responds to Enter

Upvotes: 1

Related Questions