Shiny - How to trigger an event when a selectInput object is modified OR the user makes a selection?

rmarkdown

#1

I am developing a simple web app using the Interactive Document approach with R_Markdown and Shiny. I have a series of input UI objects that get the user options, each of these modifies the next in a chain, and the final one triggers the output (a chart). So I have

  1. A map, which when clicked defines the
  2. Seasons of data available, when one is selected it gives the
  3. Soil types in the data, when one or more are selected it gives the
  4. Elevation classes in the data, when one is selected we then calculate and draw the
  5. Output chart of the selected data.

So for example there are drop down lists to choose the season and soil(s):

  output$season_selector <- renderUI({
    cat(file=stderr(), paste("render season selector"), "\n")
    selectInput("season", h4("Season?"), my$season_here, selected=my$season_sel)
  })

  output$soil_selector <- renderUI({
    cat(file=stderr(), paste("render soil selector"), "\n")
    selectInput("soil", h4("Soils?"), my$soil_here, selected=my$soil_sel, 
                selectize=FALSE, multiple=TRUE)
  })

I observe input$season, and this triggers an update of the "soil" UI element.

observeEvent(input$season, {

...

# reset soil list and default soil selected
my$soil_sel <- my$soil_here

})

However, this does invalidate input$soil (although the UI element options and selection have changed, the user has not made a selection), and so the next step in the cascade doesn't trigger. I want the following observer to trigger either when selectInput("soil") is updated OR when the user makes a selection. How do I do this?

observeEvent(input$soil, {

...

})

#2

Hi @woodward,

from my opinion the easiest way is to use an additional reactive variable e.g. rvSoilSet that is either set when the selectInput("soil") is updated (then when you reset the input) or when the user makes a selection:

observeEvent(input$soil, {
rvSoilSet <- input$soil
})

You can then trigger the next step in your selection using the new reactive variable rvSoilSet.

Best regards
Sebastian


#3

Thanks @SebastianVock, yes I've tried this but still can't get it to work properly. Sometimes it triggers twice and sometimes it doesn't trigger at all. Maybe I need to work up a repex.


#4

Ok, I think I've fixed it. I needed to use the following pattern, which resets variables further down the chain, and doesn't respond to user inputs unless the value has changed. This avoids duplicate or missing events.

 
  # reset selections
  my$soil_default <- my$soil_here
  my$soil <- my$soil_default 
  my$elev <- list(NA)

}) # end reaction to season changing

observeEvent(input$soil, {
  req(input$soil, input$soil!="NA")
  if (any(my$soil != input$soil)) {
    my$soil <- input$soil
    my$elev <- list(NA)
  }
})

#### react to change of soil ####
observeEvent(my$soil, {
  
  cat(file=stderr(), "\n")
  cat(file=stderr(), paste("change of my$soil = "))
  cat(file=stderr(), paste(my$soil), "\n")
  req(my$soil, my$soil!="NA")