rshinyshiny-reactivity

Combination of reactive and eventReactive for generating a plot


Overview: I'm using a reactive component to update the data set dynamically based on user input. This works without any issue.

Additional requirement: I want to color the plot only on click of a button. Current setting: After I click 'Color' button, the color remains even if I change the data set.

I defined the same output element inside an observeEvent block to override the default element defined in server. However, this override is permanent.

library(shiny)
shinyApp(ui = fluidPage(
  sidebarPanel(
    selectInput(inputId = "dropdown", label = "Select data set:",
                choices = c("iris", "mtcars"), selected = "iris")
  ),

  mainPanel(fluidPage(
    fluidRow(plotOutput("plot"),
             actionButton("color", "Color"))
  ))
), server = function(input, output) {
  get_data <- reactive({
    if(input$dropdown == "iris") {
      return(list(dat = iris, x = "Sepal.Length", color = "Species"))
    } else {
      return(list(dat = mtcars, x = "mpg", color = "cyl"))
    }
  })
  output$plot <- renderPlot({
    dat <- get_data()
    return(plot(dat$dat[, dat$x]))
  })

  observeEvent(input$color, {
    output$plot <- renderPlot({
      dat <- get_data()
      return(plot(dat$dat[, dat$x], col = dat$dat[, dat$color]))
    })
  })
})

Actual result: Color appears every time clicking "Color" button even if I change the data set. Expected result: Color should appear after clicking "Color" for the current data set. It should not appear once I change the data set. It should reappear only when I click "Color" button again.


Solution

  • You can explicitly observe the event that is triggered by input$dropdown:

    function(input, output) {
      get_data <- reactive({
        if(input$dropdown == "iris") {
          return(list(dat = iris, x = "Sepal.Length", color = "Species"))
        } else {
          return(list(dat = mtcars, x = "mpg", color = "cyl"))
        }
      })
      observeEvent(input$dropdown, {
        output$plot <- renderPlot({
          dat <- get_data()
          return(plot(dat$dat[, dat$x]))
        })  
      })
    
      observeEvent(input$color, {
        output$plot <- renderPlot({
          dat <- get_data()
          return(plot(dat$dat[, dat$x], col = dat$dat[, dat$color]))
        })
      })
    }