Using Enter Key with Action Button in R Shiny

Using enter key with action button in R Shiny

I was able to figure this out using the jQuery is(":focus") function, the code I used was:

$(document).keyup(function(event) {
if ($("#number").is(":focus") && (event.key == "Enter")) {
$("#goButton").click();
}
});

Shiny: Using enter key with action button on login screen

For anyone else who stumbles upon this thread, this solution (unlike the accepted solution to the above-linked SO post Using enter key with action button in R Shiny) does not require an external js script file.

The js script should have been included inside the modalDialog() instead, and inside the HTML() function, as follows:

library(shiny)
library(shinydashboard)

Logged = FALSE
my_username <- "test"
my_password <- "test"

js <- '
$(document).keyup(function(event) {
if ($("#password").is(":focus") && (event.keyCode == 13)) {
$("#ok").click();
}
});
'

ui <- dashboardPage(skin = "blue",
dashboardHeader(title = "Dashboard"),
dashboardSidebar(),
dashboardBody("Test",
verbatimTextOutput("dataInfo")
)
)

server = function(input, output, session) {

values <- reactiveValues(authenticated = FALSE)

# Return the UI for a modal dialog with data selection input. If 'failed'
# is TRUE, then display a message that the previous value was invalid.
dataModal <- function(failed = FALSE) {
modalDialog(
tags$script(HTML(js)),
textInput("username", "Username:"),
passwordInput("password", "Password:"),
footer = tagList(
# modalButton("Cancel"),
actionButton("ok", "OK")
)
)
}

# Show modal when button is clicked.
# This `observe` is suspended only whith right user credential

obs1 <- observe({
showModal(dataModal())
})

# When OK button is pressed, attempt to authenticate. If successful,
# remove the modal.

obs2 <- observe({
req(input$ok)
isolate({
Username <- input$username
Password <- input$password
})
Id_username <- which(my_username == Username)
Id_password <- which(my_password == Password)
if (length(Id_username) > 0 & length(Id_password) > 0) {
if (Id_username == Id_password) {
Logged <<- TRUE
values$authenticated <- TRUE
obs1$suspend()
removeModal()

} else {
values$authenticated <- FALSE
}
}
})

output$dataInfo <- renderPrint({
if(values$authenticated){
"OK!!!!!"
} else {
"You are NOT authenticated"
}
})

}

shinyApp(ui,server)

Also, as a side note, I believe that the js script was originally inspired by this example.

Trigger actionButton with keyboard in shiny using uiOutput

This should do:

library(shiny)

jscode <- '$(document).keyup(function(e) {
if (e.key == "Enter") {
$("#user_login").click();
}});'

ui <- fluidPage(
tags$head(tags$script(HTML(jscode))),
uiOutput("ui")
)

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

output$ui <- renderUI({
tagList(
tagAppendAttributes(passwordInput("user_pw", "Password",value = ""),`data-proxy-click` = "user_login"
),
actionButton("user_login", "Anmelden")
)
})

observeEvent(input$user_login, {
cat("clicked", "\n")
})
}

shinyApp(ui, server)

Shiny: Action button is not working after clicking enter

You'll have to bind this manually. Try implementing the following, and replace InputId with the InputId for your actionButton.

$(document).keyup(function(event) {
if(event.keyCode == 13) {
$('#InputId').click();
}
});

Shiny Responds to Enter

In your case, the problem is reactive programming and this is the reason that you need something to manage this situation. My recommendation is to use observer pattern or validate function.

  • Observer pattern: shiny implements the observer pattern which is
    useful to act when an event happens in an object (it can be a click
    in a button, new value in an input...).

  • Validate function: the functionality of this process is similar to an
    if/else statement. Indeed, there is need what is the if to check the
    parameter, if the values are wrong, there will be an error message.

To know how to use observe pattern and the validate function, click on the previous link (in the Shiny website is everything explained).

R Shiny key and actionButton binding to reactive values

The problem is that the input event only captures the keycode of the pressed key, which stays the same once the key is pressed. Shiny however only reacts if the event data changes. You need to set the event data to something new every time; e.g. the current time stamp. Look at this working example:

library(shiny)
shinyApp(ui <- pageWithSidebar(
headerPanel("Test keyboard control"),
sidebarPanel(
tags$script('$(document).on("keydown",
function (e) {
if(e.which == 68) {
Shiny.onInputChange("downButton", new Date());
} else if (e.which == 85) {
Shiny.onInputChange("upButton", new Date());
}
});
'),
actionButton("downButton", "Down"),
actionButton("upButton", "Up")
),
mainPanel(htmlOutput("text"))
),

server <- function(session, input, output) {
vals <- reactiveValues(count = 0)

observeEvent(input$downButton, {vals$count <- vals$count - 1})
observeEvent(input$upButton, {vals$count <- vals$count + 1})

output$text <- renderText(paste("Counter is:", vals$count))
}
)

Making an Action Button re-read file and recompute in Shiny

If I'm reading this right you'd like to spare your query limit by providing a local set of data to your shiny application. But if a user requests an update you'd like to trigger a query to be used in calculations.

I cannot recommend enough that you make full use of reactivity in Shiny. It is fairly rare to use an object from the global environment, especially when you intend for user inputs to manipulate those objects. You should have your base data ( in your case the tsv) load into the global environment, and then call that information into your application via a reactive dataframe. I built the below minimal example using mpg subset to the first 5 rows to simulate the .tsv on your local machine. mpg subset to 10 rows is to simulate the results of a query to a database. These two data sets get called via an if else statement dependent on an actionbutton.

library(tidyverse)
library(shiny)

# using partial mpg data to simulate un-updated data
mpg <- ggplot2::mpg[1:5,]

ui <- fluidPage(
sidebarLayout(
sidebarPanel(
actionButton("update", "Update Data"),
uiOutput('selectOpts')
),
mainPanel(
h2("This is our base data layer"),
verbatimTextOutput('print_interval1'),
h2("This is our output data"),
verbatimTextOutput('print_interval2')
)
)
)

server <- function(input, output) {

# The core of shiny is the reactivity. It's the workhorse of interactive apps.
# If possible, a data calculation should always happen in a reactive context.
working_data <- reactive({

# actionbuttons increment a value by 1, starting with 0. If input < 0 the
# user has not interacted yet. If incremented again, the reactive context
# will invalidate and re-calculate the working_data() object
if (input$update < 1) {
base_dat <-
mpg %>%
mutate(ratio = cty/hwy)
} else {
base_dat <-
ggplot2::mpg[1:10,] %>% # calling from namespace to simulate a query. Full data
mutate(ratio = cty/hwy)
}

# return our base data. Can be called with `working_data()`
data.frame(base_dat)

})

output$print_interval1 <- renderPrint({
working_data()
})

output$selectOpts <- renderUI({
# using the reactive data inside renderUI we can be flexible in our options
# this lets us adapt the UI to reactive data.
radioButtons('model',
"Select Model",
sort(unique(working_data()$model)))
})

# You can also chain reactive objects.
output_data <- reactive({
working_data() %>%
group_by(model) %>%
filter(model == input$model) %>%
summarise(m.ratio = mean(ratio))
})

output$print_interval2 <- renderPrint({
output_data() %>%
data.table()
})
}

shinyApp(ui = ui, server = server)

I also recommend looking into this post about database syncing for setting up triggers and using reactive objects as your applications get more complex. I hope that's enough to get you on the right track for both your initial question about updating data, and your comments about having your inputs react to updated data.

Using action button to set value of widget in R Shiny

Lets make the checkbox be dependant on the current_state(), we can achieve that with the first observeEvent(current_state(),{.... The reset part we just update the input$num using the second observeEvent(input$action, {... and since the checkbox is already dependant on the current_state() it will auto reset also...

library(shiny)
test_data <- c(TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE)
original_state <- 4

ui <- fluidPage(
titlePanel("Action Button Test"),
sidebarLayout(
sidebarPanel(
numericInput("num", label = h3("Select Row:"), value = original_state,max = length(test_data)),
actionButton("action", label = "Reset State")
),
mainPanel(
checkboxInput("checkbox", label = "State", value = test_data[original_state])
)
)
)

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

current_state <- reactive({
test_data[input$num]
})

observeEvent(current_state(),{
updateCheckboxInput(session, "checkbox", value = current_state())
})

observeEvent(input$action, {
updateNumericInput(session,'num', value = original_state)
})
}

shinyApp(ui = ui, server = server)


Related Topics



Leave a reply



Submit