问题
I am not an expert in html or JavaScript by any means. So, I hope for you assistance with this issue.
I thought I should provide a smaller version of my app in order to be able to explain the problem. Here is the app.R of a simple app that allows the user to write, let's say a word, in the textArea. The first letter of the word will appear automatically as the label of the action button, if the user clicks on the action button, the contents of the textArea will be updated stating whether the word the user wrote starts with a vowel or with a consonant.
library(shiny)
library(shinydashboard)
# Define UI for application
ui <- dashboardPage(
dashboardHeader(
title = "page_title"
),
dashboardSidebar(
),
dashboardBody(
tabBox(title = "app_title",
id = "id", width = "800px",
tabPanel("tab1)",
fluidRow(
column(width = 12,
box(
status = "info", solidHeader = TRUE,
collapsible = FALSE,
width = 12,
title = "textInput",
tags$textarea(id = "text_input1", rows = 2, cols = 50, "", autofocus = "autofocus"),
fluidRow(
column(width = 12,
actionButton("actionbutton1", label = textOutput("actionbutton1_label"))
)))))),
tabPanel("tab2"
))))
# Define server logic
server <- function(input, output, session) {
data1 <- eventReactive(input$actionbutton1, {substr(input$text_input1, 1, 1)})
output$actionbutton1_label <- renderPrint(cat(noquote({substr(input$text_input1, 1, 1)})))
observe({
if (input$actionbutton1 == 0) return()
isolate({
if (data1() %in% c("a", "e", "i", "o", "u")) {
updateTextInput(session, "text_input1",
value = paste(input$text_input1, "starts with a vowel", "", sep = " "))
}
else {
updateTextInput(session, "text_input1",
value = paste(input$text_input1, "starts with a consonant", "", sep = " "))
}
})
})}
# Run the application
shinyApp(ui = ui, server = server)
The problem definition: When you run the above app for the first time, you will see the cursor in the textArea because the argument autofocus = "autofocus" in the textArea tag definition, so no problem with the focus on loading. When you click on the action button, the cursor is no longer in the textArea. This may seem unnecessary in the case of this simple app, but in the case of the actual app, it's important and I'd hope to have the cursor back in the textArea after the user clicks the action button.
The issue again is that whenever the user of the app clicks on the action button, the cursor disappears from the textArea and the user of the app has to click in the text area to get the cursor back and continue with his/her input. I hope to save the user this extra click by keeping the cursor always alive and focused in the textArea no matter how many times the user uses other elements of the app interface.
Research: there are many posts online relating to how to control the position of the cursor. Among these posts, I think, and please correct me if I'm wrong, that this approach is pretty much the most relevant one to what I hope to accomplish:
http://www.mediacollege.com/internet/javascript/form/focus.html
What is it specifically that I need help with:
If you click on the above link, you will find a very interesting piece of html code that I copy here:
<form name="myform2">
<input type="text" name="mytextfield2">
<input type="button" name="mybutton" value="Set Focus" OnClick="document.myform2.mytextfield2.focus();">
</form>
Here is what I hope you're able to help me with, how and where can I embed this code in my shiny ui.R? Of course, I will have to assign a form for both the textArea and the button and I will change the names of the textArea and the button accordingly. I just need to pretty much make the above html code ui.R friendly (readable and executable). Any help with this is very much appreciated.
What I tried so far and it didn't work:
tags$head(HTML("<form name="myform2">
<input type="text" name="text_input1">
<input type="button" name="addword1" value="Set Focus" OnClick="document.myform2.text_input1.focus();">
</form>"))
As you can see, the syntax is messed up and all sorts of syntax warnings were raised up when I embedded the above code in the ui.R file.
Possibly important: I am using shiny dashboard and both the textArea ad the action button are defined in a tabPanel in a tabBox in the dashboardBody.
Thanks a lot
回答1:
Here is a working version like you asked:
library(shiny)
library(shinydashboard)
# Define UI for application
ui <- dashboardPage(
dashboardHeader(
title = "page_title"
),
dashboardSidebar(
),
dashboardBody(tags$head(tags$script(
'Shiny.addCustomMessageHandler("refocus",
function(NULL) {
document.getElementById("text_input1").focus();
});'
)),
tabBox(title = "app_title",
id = "id", width = "800px",
tabPanel("tab1",
fluidRow(
column(width = 12,
box(
status = "info", solidHeader = TRUE,
collapsible = FALSE,
width = 12,
title = "textInput",
tags$textarea(id = "text_input1", rows = 2, cols = 50, "", autofocus = "autofocus"),
fluidRow(
column(width = 12,
actionButton("actionbutton1", label = textOutput("actionbutton1_label"))
)))))),
tabPanel("tab2"
))))
# Define server logic
server <- function(input, output, session) {
data1 <- eventReactive(input$actionbutton1, {
substr(input$text_input1, 1, 1)
})
output$actionbutton1_label <- renderPrint(cat(noquote({substr(input$text_input1, 1, 1)})))
observeEvent(input$actionbutton1,{
isolate({
if (data1() %in% c("a", "e", "i", "o", "u")) {
updateTextInput(session, "text_input1",
value = paste(input$text_input1, "starts with a vowel", "", sep = " "))
}
else {
updateTextInput(session, "text_input1",
value = paste(input$text_input1, "starts with a consonant", "", sep = " "))
}
session$sendCustomMessage(type="refocus",message=list(NULL))
})
})}
# Run the application
shinyApp(ui = ui, server = server)
回答2:
So on the UI side you'll need something like this:
tags$script('
Shiny.addCustomMessageHandler("myCallbackHandler",
function(null) {
document.myform2.text_input1.focus();
});
')
Then in the observeEvent
related to the actionButton
you call this function:
session$sendCustomMessage("myCallbackHandler",list(NULL))
So anytime in the server when you call that custom handler it'll focus to the input. You may need to change the javascript in the function to make your page work since I don't know the names of the objects in your HTML.
Hope this helps.
来源:https://stackoverflow.com/questions/38362861/focusing-the-cursor-in-textarea-after-clicking-an-action-button-in-shiny