How to set focus on text input field after loading modal Dialog in R shiny app?

Viewed 182

I am building a barcode scanner application to verify that a primary barcode label matches all secondary barcode labels generated from the primary. The current iteration uses R, shiny and modal dialogs for scanning of the barcode labels.

I would like the app to autofocus on the text input field(s) after the modal pops up so that the user does not have to click the entry field or tab to it before scanning the label. I have read that the JS focus function may be appropriate but I am not sure where this function needs to be implemented. Your help is appreciated.

.libPaths(c(.libPaths(), temp <- tempdir()))
if(!require(shiny)) {install.packages("shiny", lib=temp, repos='http://cran.us.r-project.org')}
if(!require(shinyWidgets)) {install.packages("shinyWidgets", lib=temp, repos='http://cran.us.r-project.org')}
if(!require(shinyalert)) {install.packages("shinyalert", lib=temp, repos='http://cran.us.r-project.org')}
if(!require(devtools)) {install.packages("devtools", lib=temp, repos='http://cran.us.r-project.org')}
if(!require(shinyBarcode)) {devtools::install_github("CannaData/shinyBarcode")}
if(!require(shinyjs)) {install.packages("shinyjs", lib=temp, repos='http://cran.us.r-project.org')}
if(!require(V8)) {install.packages("V8", lib=temp, repos='http://cran.us.r-project.org')}

library(shiny)
library(shinyWidgets)
library(shinyalert)
library(shinyBarcode)
library(shinyjs)
library(V8)

options(shiny.sanitize.errors = TRUE)

options(rsconnect.max.bundle.size="xxxlarge")
  
ui <- fluidPage(
  
  # must include javascript dependencies
  useShinyalert(), # Set up shinyalert
  
  shinyBarcode::includeJsBarcode(cdn = TRUE),
  shinyBarcode::barcodeOutput("barcode"),

  useShinyjs(),
  extendShinyjs(script = "beep.js"),
  extendShinyjs(script = "beep2.js"),

)

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

  vals <- reactiveValues(txt = NULL)
  
  # Create modals
  primary <- function(failed = FALSE) {
    modalDialog(
      textInput("txt", "Scan primary tube"),
      footer = NULL,
      actionButton("reset", "Reset")
    )
  }
  
  secondary <- function(failed = FALSE) {
    modalDialog(
      textInput("txt2", "Scan secondary tube"),
      footer = NULL,
      actionButton("reset", "Reset")
    )
  }
  
  # Show modal on startup
  showModal(primary())

  observeEvent(input$txt, {
    if (!is.null(input$txt) && nzchar(input$txt)) {
      vals$txt <- input$txt
      removeModal()
      showModal(secondary())
    } else {
      showModal(primary(failed = TRUE))
    }
  })
  
  observeEvent(input$txt2, {
    if (!is.null(input$txt2) & nzchar(input$txt2) & input$txt2!="Reset") {
      vals$txt2 <- input$txt2
      removeModal()
      if (vals$txt2==vals$txt) {
        js$beep()
        showModal(secondary())
      }
      else if (vals$txt2!=vals$txt) {
        js$beep2()
        shinyalert("Error", "Primary and secondary labels do not match", type = "error")
        showModal(secondary())
      }
    } else if (!is.null(input$txt2) & nzchar(input$txt2) & input$txt2=="Reset"){
      showModal(primary())
    } else {
      showModal(secondary(failed = TRUE))
    }
  })
  
  observeEvent(input$reset, {
    showModal(primary())
    })
  
  output$barcode <- shinyBarcode::renderBarcode(vals$txt)

}

shinyApp(ui = ui, server = server)

0 Answers
Related