Search code examples
rshinyaction-button

R Shiny - How do I toggle between two different plots using an action button


In my app, I want plot1 to display by default, and then if an action button is clicked, have plot2 replace plot1. If it is clicked again, revert to plot1, and so on.


server <- function(input, output, session) {
     plot1 <- (defined here)
     plot2 <- (defined here)
  
     which_graph <- reactive({
        if (input$actionbutton == 1) return(plot1)
        if (input$actionbutton == 2) return(plot2)
      })
    
     output$plot <- renderPlot({   
        which_graph()
    
      }) 
} 

Solution

  • You can create a reactiveValue and use an actioButton to toggle that value. For example

    library(shiny)
    
    ui <- fluidPage(
      plotOutput("plot"),
      actionButton("button", "Click")
    )
    
    server <- function(input, output, session) {
      whichplot <- reactiveVal(TRUE)
      plot1 <- ggplot(mtcars) + aes(mpg, cyl) + geom_point()
      plot2 <- ggplot(mtcars) + aes(hp, disp) + geom_point()
      
      observeEvent(input$button, {
        whichplot(!whichplot())
      })
      
      which_graph <- reactive({
        if (whichplot()) {
          plot1
        } else {
          plot2
        }
      })
      
      output$plot <- renderPlot({   
        which_graph()
      }) 
    }
    
    shinyApp(ui, server)
    

    Here whichplot starts off as TRUE and then evertime you press the actionButton it toggles between TRUE/FALSE. This way you are not changing the value of the actionButton; you are just updating state each time it's pressed.

    If your plots need any input from the user, you can make them reactive as well

    ui <- fluidPage(
      selectInput("column", "Column", choices=names(mtcars)),
      plotOutput("plot"),
      actionButton("button", "Click")
    )
    server <- function(input, output, session) {
      whichplot <- reactiveVal(TRUE)
      plot1 <- reactive({ggplot(mtcars) + aes(mpg, .data[[input$column]]) + geom_point()})
      plot2 <- reactive({ggplot(mtcars) + aes(.data[[input$column]], disp) + geom_point()})
      
      observeEvent(input$button, {
        whichplot(!whichplot())
      })
      
      which_graph <- reactive({
        if (whichplot()) {
          plot1()
        } else {
          plot2()
        }
      })
      
      output$plot <- renderPlot({   
        which_graph()
      }) 
    }