问题描述
我该如何做,以便Shiny稍等一会儿,让用户输入其邮政编码(无需使用按钮)。我面临的问题是,如果用户输入邮政编码的速度不够快,它将迅速跳至错误。 编辑:
- 我在此应用中还有其他用户输入,但我在此问题中对其进行了简化。我希望所有其他输入都能立即做出反应,因为它们是radioButtons。我认为按“返回”键仍会执行与按钮相同的操作,这不是我想要的。我在考虑只将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
)
)
}
})
})
解决方法
您可以使用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
))
}
}
)
})
,
添加了JS代码,输入$ keyPressed,当在任意位置按下“返回”键时,它将接收一个随机数。
library(shiny)
js <- '
$(document).on("keyup",function(e) {
if(e.keyCode == 13){
Shiny.onInputChange("keyPressed",Math.random());
}
});
'
shinyApp(ui <- fluidPage(tags$script(js),sidebarPanel(
"",label = "Enter your zipcode.",value = 98125),textOutput("zip")
)),session) {
observeEvent(input[["keyPressed"]],{
#limits zipcode input to 5 numbers only
if (nchar(input$zipcode) != 5)
{
updateTextInput(session,value = 98125)
showModal(
modalDialog(
title = "Error!",easyClose = TRUE
)
)
}
if (is.na(as.numeric(input$zipcode)))
{
showModal(
modalDialog(
title = "Error!",easyClose = TRUE
)
)
}
output$zip <- renderText(input$zipcode)
})
})