我构建了一个 Shiny 应用程序,如果用户在 numericInput 中输入非数字值,该应用程序就会弹出消息。下面的代码就是这样做的(使用shinyBS
(,但它的反应太快了。如果用户开始输入文本,但需要考虑要输入的数字,则会弹出消息。我希望观察器事件在输入失去焦点时触发,以便用户有时间输入完整值,并且只有当他们移动到下一个输入时,观察器事件才会处理错误。有什么建议吗?如果有更好的解决方案,我不会坚持使用shinyBS
,我像 4 年前一样构建了这个应用程序,从那时起,Shiny 宇宙已经有了长足的发展。
library(shinyBS)
library(shiny)
ui<-shinyUI(fluidPage(
fluidRow(
numericInput("value","My Value",value=0),
bsModal("number_Message", "", trigger="", size = "small","This field only accepts numeric values.")
)
))
server<-shinyServer(function(input, output, session){
output$value<-renderText({input$value})
observeEvent(input$value,{
# browser()
if(is.na(as.numeric((input$value)))==T){
toggleModal(session, "number_Message",toggle="toggle")
updateNumericInput(session,"value","My Value",value=0)
}
})
})
shinyApp(ui = ui, server = server)
最好的办法可能是使用一个小的自定义 js 脚本在失去焦点时注册事件处理程序。然后,回调可以向 Shiny 发送自定义消息,也可以直接在客户端触发对话框。
假设您仍然希望服务器处理它,请在www
目录中创建一个单独的文件
// www/customMessage.js
$(document).ready(function() {
// initialize a counter
var n = 0;
// create a handler
$("#value").on("blur", function(){
// increment the counter each time input loses focus
n++;
// send message to Shiny
Shiny.onInputChange("count", n);
});
});
然后在 UI 定义中使用includeScript('www/customMessage.js')
,并在服务器定义中将触发器从input$value
更改为input$count
。
我很高兴你没有执着于shinyBS,因为它扰乱了jquery功能来添加事件处理程序。还有其他选择,但 Shiny 也有一个原生模态。总而言之,您的应用程序代码将看起来像
library(shiny)
ui <- shinyUI(fluidPage(
includeScript("www/customMessage.js"),
fluidRow(
numericInput("value","My Value",value=0)
)
))
server<-shinyServer(function(input, output, session){
output$value<-renderText({input$value})
observeEvent(input$count,{
if(is.na(as.numeric((input$value)))==T){
showModal(modalDialog(
title = "Invalid Input",
"This field only accepts numeric values."
))
updateNumericInput(session,"value","My Value",value=0)
}
})
})
shinyApp(ui = ui, server = server)