Multiple and nested observeEvent in shinyapp

Dear Community,
I have encountered a problem with using multiple and consecutive observeEvents.

I have a shinyapp that runs a API, and that call takes a few minutes.

So after my user sets all the parameters for the API I put an actionbutton connected with observeEvent to download the data.

After the data has been downloaded the user sets all the parameters to perform an elaboration. The processing starts if he presses an actionButton connected with an observeEvent.

Then the user can decide to change the data to be downloaded, visualized and analyzed and when he tries to modify the API setting and presses the first actionButton both the downloading and the processing starts and I don't understand why since the processing is linked to the second actionbutton which should block the data flow.

And as if pressed such actionbutton, are like doors that remain open and where the data flows without the control of the second actiobutton.

So I wanted to ask you if you know a way to block the flow of data between the first and the second observeEvent, so as to allow the correct setting of parameters and subsequent processing.

Hi,

It is terribly difficult to know exactly what is going on without a reprex (FAQ: How to do a minimal reproducible example ( reprex ) for beginners) of sorts. Reactivity is already complex and becomes even worse with multiple events like this. Think you can make a simple app that has a set of buttons with observeEvents to mimic your app in the most simple way?

If not, I would suggest looking at shiny::isolate. This might stop the flow between doors as you describe it. We typically use it to limit continous reactivity.

Hi,

I will provide to you a simple reproducible example as soon as possible.

For now thanks for the suggest provided.

Marco

In order to properly mimic the problem I encountered, you would have to first choose a dataset, then filter by a few columns, and then change the dataset.

I would like to stop the flow between the two observeEvents

library(shiny)
library(palmerpenguins)
library(DT)

dataset_1<-penguins
dataset_2<-iris

ui <- fluidPage(
  titlePanel("Rstudio community issue"),
  
  sidebarLayout(
    sidebarPanel(
      selectInput(inputId = "select_dataset",
                  label = "Select the dataset to visualize",
                  choices = c("Penguin dataset"="dataset_1",
                              "Iris dataset"="dataset_2")),
      actionButton("dataset_selection",
                   label = "Select the dataset"),
      br(),
      br(),
      uiOutput("more_selection"),
      uiOutput("look_dataset")),
    mainPanel(uiOutput("datatable"),
              uiOutput("last_datatable"))
  )
)

server <- function(input, output) {
  
  observeEvent(input$dataset_selection, {
    
    dataset_to_use <- switch(input$select_dataset,
                             "dataset_1"=dataset_1,
                             "dataset_2"=dataset_2)
    
    output$datatable<-renderUI({
      dataTableOutput("datatable_1")
    })
    
    output$datatable_1<-renderDT({
      datatable(dataset_to_use)
    })
    
    output$more_selection<-renderUI({
      wellPanel(
        selectInput("filter_to_analyze",
                    label = "Select variable to see",
                    choices = names(dataset_to_use),
                    multiple = TRUE))
    })
    
    output$look_dataset<-renderUI({
      actionButton("run_analysis",
                   label = "Run Analysis")
    })
    
    
    observeEvent(input$run_analysis, {
      
      dataset_filtered <- dataset_to_use %>% 
        dplyr::select(input$filter_to_analyze)
      
      output$last_datatable<-renderUI({
        dataTableOutput("datatable_2")
      })
      
      output$datatable_2<-renderDT({
        datatable(dataset_filtered)
      })
      
    })
    
    
  })
  
}

shinyApp(ui, server)

There is some parameters that i could pass to the second observeEvent in order to block the flow?

Hi,

There seems to be some misunderstanding of what observers and reactives do, in general if you're creating a reactive dataset you should use reactive() rather than observe().
In your case, you want the dataset to only update in response to a single action so you'd use the reactive equivalent of observeEvent(), which is eventReactive().
If you want to understand the difference between reactive() and observe() better, I'd recommend this talk (and part 2) by Joe Cheng.

Additionally, observers (like observeEvent()) should almost never be used to create other observers (you should never have to nest observeEvent()s like you did in your example. In your first post you mention doors that remain open and that is more or less correct, observeEvent() essentially creates a listener so if you nest them, every time it is run it is creating a new observer.

I've put below your example, using eventReactive instead of observeEvent. Important point: when you call a reactive dataset created with eventReactive remember to call it as a function (dataset_to_use() rather than dataset_to_use).

Hope that helps.

library(shiny)
library(palmerpenguins)
library(DT)

dataset_1<-penguins
dataset_2<-iris

ui <- fluidPage(
  titlePanel("Rstudio community issue"),
  
  sidebarLayout(
    sidebarPanel(
      selectInput(inputId = "select_dataset",
                  label = "Select the dataset to visualize",
                  choices = c("Penguin dataset"="dataset_1",
                              "Iris dataset"="dataset_2")),
      actionButton("dataset_selection",
                   label = "Select the dataset"),
      br(),
      br(),
      uiOutput("more_selection"),
      uiOutput("look_dataset")),
    mainPanel(uiOutput("datatable"),
              uiOutput("last_datatable"))
  )
)

server <- function(input, output) {
  

  dataset_to_use <- eventReactive(input$dataset_selection, {
    switch(input$select_dataset,
           "dataset_1"=dataset_1,
           "dataset_2"=dataset_2)
  })
  
  
  output$datatable<-renderUI({
    DT::dataTableOutput("datatable_1")
  })
    
  output$datatable_1<-renderDT({
    datatable(dataset_to_use())
  })
    
  output$more_selection<-renderUI({
    wellPanel(
      selectInput("filter_to_analyze",
                  label = "Select variable to see",
                  choices = names(dataset_to_use()),
                  multiple = TRUE))
  })
    
  output$look_dataset<-renderUI({
    actionButton("run_analysis",
                 label = "Run Analysis")
  })
    
    
  dataset_filtered <- eventReactive(input$run_analysis, {
    dataset_to_use() %>% 
      dplyr::select(input$filter_to_analyze)
  })

  output$last_datatable<-renderUI({
    DT::dataTableOutput("datatable_2")
  })
      
  
  output$datatable_2<-renderDT({
    DT::datatable(dataset_filtered())
  })
  
}

shinyApp(ui, server)
2 Likes

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.