1

I got an app that when you click on an actionButton, it should set an input to a certain value; and a click action should be made through shinyjs. However, only the first thing is happening; and I don't know how to make the second one happen. Or maybe it IS happening; but the data inside the reactive object is not getting updated.

Heres a minimal reprex:

library(shiny)

ui <- fluidPage(
  shinyjs::useShinyjs(),
  
  selectInput("selector", label = "Carb selector", choices = unique(mtcars$carb)),
  actionButton("generate", "OK!"),
  tableOutput("results"),
  actionButton("reset", "RESET"),
  
)

server <- function(input, output, session) {
  
  data <- reactive({
    req(input$generate)
    isolate(
    mtcars %>% filter(carb == input$selector)
    )
  })
  
  output$results <- renderTable(data())

  observeEvent(input$reset, {
    
    updateSelectInput(session, 
                      inputId = "selector",
                      label = "Carb selector updated",
                      choices = unique(mtcars$carb),
                      selected = 1)
    
    shinyjs::click("generate")#This does not seem trigger when you hit reset!
    
  })
    
}

shinyApp(ui, server)

2 Answers 2

1

Why this behavior?

The architecture of your code is a bit questionable, but I will point out why it is behaving this way.

To understand this, let's first break the observer on input$reset into two:

  observeEvent(input$reset, {
    updateSelectInput(
      session,
      inputId = "selector",
      label = "Carb selector updated",
      choices = unique(mtcars$carb),
      selected = 1
    )
  })

  observeEvent(input$reset, {
    shinyjs::click("generate") # This does not seem trigger when you hit reset!
  })

After that, let's have a look at the documentation of updateSelectInput:

The input updater functions send a message to the client, telling it to change the settings of an input object. The messages are collected and sent after all the observers (including outputs) have finished running.

And there lies the answer. In other words, shinyjs::click("generate") will always execute before update*Input() effects kick in.

Basically, this is the flow:

1. User clicks 'reset' btn
2. That leads to a click on 'generate' btn
3. The `data()` reactive is re-evaluated
4. All observers are re-evaluated
5. `update*Input()` sends updates to the client

Suggested solution

We can use number 4 above to our advantage by having a reactiveVal() that always has the most current value of 'selector' and is a step ahead of update*Input().

I have made a few changes to your code to make it more explicit and straight to the point.

Demo

library(shiny)
library(dplyr)

ui <- fluidPage(
  shinyjs::useShinyjs(),
  selectInput("selector", label = "Carb selector", choices = unique(mtcars$carb)),
  actionButton("generate", "OK!"),
  tableOutput("results"),
  actionButton("reset", "RESET"),
)

server <- function(input, output, session) {
  rv_selector <- reactiveVal()
  observeEvent(input$selector, rv_selector(input$selector))

  data <- reactive({
    mtcars %>% filter(carb == rv_selector())
  }) |> bindEvent(input$generate)

  output$results <- renderTable(data())

  observeEvent(input$reset, {
    updateSelectInput(
      session,
      inputId = "selector",
      label = "Carb selector updated",
      choices = unique(mtcars$carb),
      selected = 1
    )
    rv_selector(1) # Ensures server is updated before the client
    shinyjs::click("generate")
  })
}

shinyApp(ui, server)
Sign up to request clarification or add additional context in comments.

Comments

1

It is triggering, but you don't see it in your dataset as you are not changing anything. Try this

library(shiny)

ui <- fluidPage(
  shinyjs::useShinyjs(),

  selectInput("selector", label = "Carb selector", choices = unique(mtcars$carb)),
  actionButton("generate", "OK!"),
  tableOutput("results"),
  actionButton("reset", "RESET"),

)

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

  data <- reactive({ 
    req(input$generate)
    # isolate(
      mtcars %>% filter(carb == input$selector) %>%
        dplyr::mutate(clickedtimes = input$generate)
    # )
  })

  output$results <- renderTable(data())

  observeEvent(input$reset, {

    updateSelectInput(session,
                      inputId = "selector",
                      label = "Carb selector updated",
                      choices = unique(mtcars$carb),
                      selected = 1)

    shinyjs::click("generate")#This does not seem trigger when you hit reset!

  })
  observe({print(input$generate)})
}

shinyApp(ui, server)

2 Comments

Ok, but the selectInput changes to 1. I would like to see what should come next: the clicking of input$generate and therefore the filtered data by carb == 1
Comment out the isolate and it works. Please try the updated code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.