James
James

Reputation: 526

Add lag before observe event updates numeric input

I have a shiny app with a bunch of numeric inputs. Some of them are dependent on the value of others. As an example, let's say that I need input_1 to be changed if the entered input_2 is greater, such that input_1 = input_2 + 1. The problem is that if the user inputs their value too slowly, it takes the first digit of the entered input_2, for instance 5, and makes the input_1 equal to 6, even if you finish typing 540.

Here's an example:


library(shiny)

ui <- fluidPage(
  numericInput("input1", "Input 1:", 0),
  numericInput("input2", "Input 2:", 0)
)

server <- function(input, output, session) {
  
  
  observeEvent(input$input2, {
    if (input$input2 > input$input1) {
      updateNumericInput(session, "input1", value = input$input2 + 1)
    }
  })
  

}

shinyApp(ui, server)


I have tried using invalidateLater, or debounce, but I believe I haven't done it correctly since the output still changes almost immediately. Ideally it would only update once focus is lost, but I don't want to add js to my code. So having a fixed timer to update seems like a good middle ground. Any ideas?

Upvotes: 1

Views: 135

Answers (2)

James
James

Reputation: 526

Here's an example using the delay function from the shinyjs package:

library(shiny)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(), # call for shinyjs to be used in the ui part of the dashboard
  numericInput("value1",
               "Value 1:",
               value = 40),
  numericInput("value2",
               "Value 2:",
               value = 50)
)

server <- function(input, output, session) {
  

  
  
  observeEvent(input$value1, {
    if (input$value1 > input$value2) {
      delay(2000, # the delay in milliseconds that is imposed
            updateNumericInput(session = session, "value2", value = input$value1 + 1))
    }
  })
  
  
}

shinyApp(ui, server)

In the event that value1 should be greater than value2, after 2 sec., value2 will be updated to be equal to 1 + value1.

Upvotes: 1

ismirsehregal
ismirsehregal

Reputation: 33530

As you have already mentioned debounce is the right way to go:

library(shiny)

ui <- fluidPage(
  numericInput("input1", "Input 1:", 0),
  numericInput("input2", "Input 2:", 0)
)

server <- function(input, output, session) {
  
  input2_d <- debounce(reactive({input$input2}), 1000L)
  
  observeEvent(input2_d(), {
    if (input2_d() > input$input1) {
      updateNumericInput(session, "input1", value = input2_d() + 1)
    }
  })
}

shinyApp(ui, server)

Upvotes: 1

Related Questions