Reputation: 1779
I want two different events to trigger an observer. It was suggested here that this should work. But it seems that it depends only on the second event.
observeEvent({
input$spec_button
mainplot.click$click
}, { ... } )
Have a look at the example.
ui <- shinyUI(bootstrapPage(
actionButton("test1", "test1"),
actionButton("test2", "test2"))
)
server <- shinyServer(function(input, output) {
observeEvent({
input$test1
input$test2
}, {
print('Hello World')
})
})
shinyApp(ui, server)
Once you click button test1 nothing happens. If you click button test2 it prints to your console. Once test2 button was pressed clicking test1 prints the message. That is a strange behaviour.
Another suggestion in that link was to use
list(input$test1, input$test2)
Which prints the message even without clicking the buttons.
Upvotes: 41
Views: 40771
Reputation: 347
In my case I have an action button within a modal. In order to prevent the modal button initialization from triggering the observe event, I must generate 2 separate observe events. This method works.
employee <- shiny::reactiveVal(DBI::dbReadTable(pool, "employee") |>
dplyr::mutate(actions = ""))
shiny::observeEvent(label = "Refresh employee table on add", eventExpr =
input$submit, {
employee(DBI::dbReadTable(pool, "employee"))
}, ignoreInit = TRUE)
shiny::observeEvent(label = "Refresh employee on delete", eventExpr =
input$yes_button, {
employee(DBI::dbReadTable(pool, "employee"))}, ignoreInit = TRUE)
Upvotes: 1
Reputation: 2344
Using the |
operator in the observeEvent()
eventExpr
won't work if the inputs are not numeric, logical or complex types.
For example, notice the message at the end of running this simple Shiny app with an actionButton()
and a selectInput()
used inside the observeEvent()
eventExpr
:
library(shiny)
ui <- shinyUI(bootstrapPage(
selectInput("test1", "test1", choices = c("a", "b")),
actionButton("test2", "test2"))
)
server <- shinyServer(function(input, output) {
observeEvent(input$test1 | input$test2,
{
print('Hello World')
})
})
shinyApp(ui, server)
#>
#> Listening on http://127.0.0.1:6563
#> Warning: Error in |: operations are possible only for numeric, logical or
#> complex types
Created on 2022-04-02 by the reprex package (v2.0.1)
Instead, you can create a list of the inputs inside the observeEvent()
and include ignoreInit = TRUE
if you wish to not print "Hello World" on app initialization. This approach accommodates any input types.
library(shiny)
ui <- shinyUI(bootstrapPage(
selectInput("test1", "test1", choices = c("a", "b")),
actionButton("test2", "test2"))
)
server <- shinyServer(function(input, output) {
observeEvent(ignoreInit = TRUE, list(
input$test1,
input$test2
),
{
print('Hello World')
})
})
shinyApp(ui, server)
If the observeEvent(list(input$a, input$b), {...})
approach doesn't float your boat, then I can recommend the reactive({list(input$a, input$b})
approach which goes like this:
library(shiny)
ui <- shinyUI(bootstrapPage(
selectInput("test1", "test1", choices = c("a", "b")),
actionButton("test2", "test2"))
)
server <- shinyServer(function(input, output) {
event_trigger <- reactive({
list(input$test1, input$test2)
})
observeEvent(ignoreInit = TRUE, event_trigger(),
{
print('Hello World')
})
})
shinyApp(ui, server)
This approach has the advantage of being portable, meaning you can use it as the eventExpr
for multiple observeEvent()
calls (or other listeners) if needed.
Upvotes: 24
Reputation: 202
observeEvent is a wrapper for complex observe cases. In this particular case of an action when one or other reactive value changes, one could use a simple observe. This works:
require(shiny)
ui <- basicPage(
actionButton("test1", "test1"),
actionButton("test2", "test2")
)
server <- function(input, output, session){
observe( {
input$test1
input$test2
if(input$test1==0 && input$test2==0){
return()
}
print('Hello World')
})
}
shinyApp(ui, server)
There is a point in using observeEvent with options to eliminate the return() call:
ui <- basicPage(
actionButton("test1", "test1"),
actionButton("test2", "test2")
)
server <- function(input, output, session){
observeEvent(input$test1 | input$test2, { print('Hello World') } , ignoreInit = TRUE)
}
shinyApp(ui, server)
Upvotes: 3
Reputation: 29417
This should do it, note that you still have to check if the buttons were clicked as mentioned by @MrFlick
#rm(list = ls())
library(shiny)
ui <- shinyUI(bootstrapPage(
actionButton("test1", "test1"),
actionButton("test2", "test2"))
)
server <- shinyServer(function(input, output) {
toListen <- reactive({
list(input$test1,input$test2)
})
observeEvent(toListen(), {
if(input$test1==0 && input$test2==0){
return()
}
print('Hello World')
})
})
shinyApp(ui, server)
#rm(list = ls())
library(shiny)
ui <- shinyUI(bootstrapPage(
actionButton("test1", "test1"),
actionButton("test2", "test2"))
)
server <- shinyServer(function(input, output) {
observeEvent(input$test1 | input$test2, {
if(input$test1==0 && input$test2==0){
return()
}
print('Hello World')
})
})
shinyApp(ui, server)
Upvotes: 42