闪亮:将焦点设置为在 modalDialog 中输入

Shiny: set focus to input in modalDialog

我正在尝试将焦点设置到闪亮的 modalDialog 中的 textInput。我正在使用 shinyjs。根据 shinyjs 文档的指导,我想出了以下代码,但它没有达到我的预期:

library(shiny)
library(shinyjs)

jscode <- "
shinyjs.refocus = function(e_id) {
  document.getElementById(e_id).focus();
}"

# Define UI for application that draws a histogram
ui <- fluidPage(
    shinyjs::useShinyjs(),
    shinyjs::extendShinyjs(text = jscode, functions = "refocus"),
    # Application title
    titlePanel("Old Faithful Geyser Data"),

    # Sidebar with a slider input for number of bins 
    sidebarLayout(
        sidebarPanel(
            sliderInput("bins",
                        "Number of bins:",
                        min = 1,
                        max = 50,
                        value = 30),
            actionButton("show", "Show Modal")
        ),

        # Show a plot of the generated distribution
        mainPanel(
           plotOutput("distPlot")
        )
    )
)

# Define server logic required to draw a histogram
server <- function(input, output) {

    output$distPlot <- renderPlot({
        # generate bins based on input$bins from ui.R
        x    <- faithful[, 2]
        bins <- seq(min(x), max(x), length.out = input$bins + 1)

        # draw the histogram with the specified number of bins
        hist(x, breaks = bins, col = 'darkgray', border = 'white')
    })
    
    observeEvent(input$show, {
        showModal(ui = modalDialog(title = "my modal dialog",
                                   textInput("text_1", label = "text 1"),
                                   textInput("text_2", label = "text 2"),
                                   js$refocus("text_1")))
    })
    
}

# Run the application 
shinyApp(ui = ui, server = server)

modalDialog 是用两个 textInput 创建的,但两个输入都没有焦点。如何在第一个输入上强制输入?我想避免额外的点击以将焦点设置在输入上。感谢您的帮助。

你的问题是你的 js$refocus 被调用时, modal 还没有设置。如果你在开发工具中打开控制台,你会看到出现错误。

更好的选择是注册一个事件侦听器,它会在模式显示时立即触发。查看 docs of modal 可以看到,有一个 shown.bs.modal 事件,它在加载模式时触发。

事件在 .modal 元素处触发,该元素不存在,但由于事件冒泡,我们可以在 <body> 处收听此事件,您可以在那里做出反应。

足够的理论,这是代码(不需要shinyjs):

library(shiny)

## create an event listener at <body> which fires as soon as the modal is shown
## sets the focus to the first text element (adapt if needed)
jscode <- HTML("$('body').on('shown.bs.modal', (x) => 
                   $(x.target).find('input[type=\"text\"]:first').focus())")

# Define UI for application that draws a histogram
ui <- fluidPage(
   # Application title
   titlePanel("Old Faithful Geyser Data"),
   tags$header(tags$script(type = "text/javascript", jscode)),
   # Sidebar with a slider input for number of bins 
   sidebarLayout(
      sidebarPanel(
         sliderInput("bins",
                     "Number of bins:",
                     min = 1,
                     max = 50,
                     value = 30),
         actionButton("show", "Show Modal")
      ),
      
      # Show a plot of the generated distribution
      mainPanel(
         plotOutput("distPlot")
      )
   )
)

只需从您的模式中删除 js$refocus 功能,您应该没问题。这是显示效果的 gif: