I've built a Shiny app that has a popup message if a user puts in a non-numeric value into a numericInput. The code below does just that (using shinyBS), but it reacts too quickly. If the user starts entering text, but needs to think a little about the number to put in, the message pops up. I'd like the observeEvent to trigger when the input loses focus, so the user has time to enter the full value, and only when they move on to the next input does the observeEvent handle the error. Any suggestions? I'm not wedded to using shinyBS if there's a better solution out there, I built this app like 4 years ago and the Shiny universe has grown considerably since then.
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)
Your best bet is probably using a small custom js script to register an event handler on the loses focus. The callback could then either send a custom message to Shiny or trigger a dialog box directly on the client side.
Assuming you still want the server to handle it, create a separate file in your www directory
// 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);
});
});
Then use includeScript('www/customMessage.js') in your UI definition and change the trigger from input$value to input$count in the server definition.
I'm glad that you're not wedded to shinyBS, because it messes with the jquery functionality to add the event handler. There are other options out there, but Shiny also has a native modal. All together, your app code would look something along the lines of
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With