Reputation: 365
After my R Shiny app has loaded, I would like to set focus to the selectInput
element, so that the user can immediately select an item by up-down arrows and hit enter.
I was trying to capture the JavaScript load
event, send it to R and than use the Shiny.addCustomMessageHandler
to set focus of the selectInput
element.
As an intermediate step, I was also trying, to use the click event from an actionButton
to trigger the element focus. Although I think most parts should be in the code, the load
event does not get transmitted to the server and the focus part does get picked up by JavaScript.
This post focusing the cursor in textArea after clicking an action button in shiny also did not help me enough to get it to the finish line.
This is what I have so far:
library(shiny)
ui <- fluidPage(
tags$head(tags$script('
window.addEventListener("load", function(){
alert("Loaded");
Shiny.setInputValue("loaded", 1) // new identical function to Shiny.onInputChange
});
')),
tags$head(tags$script('
Shiny.addCustomMessageHandler("focus", function(null) {
document.getElementById("select").focus()
});
')),
headerPanel("Focus", windowTitle = "Focus"),
fluidRow(
column(width = 2, class = "panel",
selectInput("select", label = "Your Choice", choices = c("Choice 1", "Choice 2"), selectize = TRUE),
actionButton("click", "Click")
),
column(width = 10,
textOutput("text")
)
)
)
server = function(input, output, session) {
observeEvent(input$loaded, {
session$sendCustomMessage("focus",list(NULL))
print("Loaded")
})
observeEvent(input$select, {
print("Selected")
})
observeEvent(input$click, {
session$sendCustomMessage("focus",list(NULL))
print("Clicked")
})
output$text <- renderText({
})
}
shinyApp(ui = ui, server = server)
Thank you for your help.
Upvotes: 3
Views: 1387
Reputation: 84649
Open the console (Ctrl+Shift+i with Chrome), you will see there are some errors in your JS code.
The main one is that shiny
is not ready yet when you open the app, so the function Shiny.setInputValue
is not found.
To be sure shiny
is ready, use:
$(document).on("shiny:connected", function(){
......
});
Now, after some multiple trials, I found that the element to be "focused" is not the entire select
element. It is its div
subelement with class selectize-input
, that you can select with $("#select ~ .selectize-control > .selectize-input")
.
Finally, the good action to perform is not focus
, it is click
. Here is the full app:
library(shiny)
js <- '
$(document).on("shiny:connected", function(){
alert("Loaded");
Shiny.setInputValue("loaded", 1);
Shiny.addCustomMessageHandler("focus", function(x){
$("#select ~ .selectize-control > .selectize-input").click();
});
});
'
ui <- fluidPage(
tags$head(tags$script(HTML(js))),
headerPanel("Focus", windowTitle = "Focus"),
fluidRow(
column(width = 2, class = "panel",
selectInput("select", label = "Your Choice",
choices = c("Choice 1", "Choice 2"), selectize = TRUE),
actionButton("click", "Click")
),
column(width = 10,
textOutput("text")
)
)
)
server = function(input, output, session) {
observeEvent(input$loaded, {
session$sendCustomMessage("focus", list(NULL))
print("Loaded")
})
observeEvent(input$select, {
print("Selected")
})
observeEvent(input$click, {
session$sendCustomMessage("focus", list(NULL))
print("Clicked")
})
output$text <- renderText({
})
}
shinyApp(ui = ui, server = server)
Upvotes: 7