rshinytabsaction-button

Is it possible to have the same actionButton in 2 tabs [Shiny]?


I am trying to create an app which has 3 tabs:

It works perfectly. However, when I change the opacity in Tab 3 and I want to update the plot, the actionButton from the Tab 3 doesn't work. However, if you click the actionButton from Tab 2 after having changed the opacity, the plot updates.

image 1

So... for that reason, I was wondering if there was a way to have the same actionButton in two tabs.

The code:

library(shiny)
library(dplyr)
library(ggplot2)

hist_function <- function(DF, bins, alpha){
  hist <- DF %>% 
    ggplot(aes(value)) +
    geom_histogram(aes(y=..density.., fill = id), bins=bins, col="black", alpha=alpha) +
    geom_density() +
    facet_grid(id ~ .) + 
    ggtitle("My histogram....") +
    theme(strip.text.x = element_blank(),strip.text.y = element_blank()) 
  
  return(hist)
}
  
ui <- fluidPage(
  
  titlePanel("My app"),
  
  sidebarLayout(
    sidebarPanel(
      tabsetPanel(
        
        tabPanel("Tab1",
                 checkboxInput("log2", "Log2 transformation", value = FALSE),
                 actionButton("submit", "Submit")
        ),
        
        tabPanel("Tab2",
                 sliderInput("bins",
                             "Number of bins:",
                             min = 1,
                             max = 50,
                             value = 10),
                 actionButton("show_plot", "See the plot")
        ),
        
        tabPanel("Tab3",
                 numericInput("alpha", "Opacity of the histogram", value=0.2),
                 actionButton("show_plot", "See the plot")
        )
        
      )
    ),
    
    mainPanel(
      plotOutput("histogram"),

    )
  )
)


server <- function(input, output) {
  
  val1 <- c(2.1490626,3.7928443,2.2035281,1.5927854,3.1399245,2.3967338,3.7915825,4.6691277,3.0727319,2.9230937,2.6239759,3.7664386,4.0160378,1.2500835,4.7648343,0.0000000,5.6740227,2.7510256,3.0709322,2.7998003,4.0809085,2.5178086,5.9713330,2.7779843,3.6724801,4.2648527,3.6841084,2.5597235,3.8477471,2.6587736,2.2742209,4.5862788,6.1989269,4.1167091,3.1769325,4.2404515,5.3627032,4.1576810,4.3387921,1.4024381,0.0000000,4.3999099,3.4381837,4.8269218,2.6308474,5.3481382,4.9549753,4.5389650,1.3002293,2.8648220,2.4015338,2.0962332,2.6774765,3.0581759,2.5786137,5.0539080,3.8545796,4.3429043,4.2233248,2.0434363,4.5980727)
  val2 <- c(3.7691229,3.6478055,0.5435826,1.9665861,3.0802654,1.2248374,1.7311236,2.2492826,2.2365337,1.5726119,2.0147144,2.3550348,1.9527204,3.3689502,1.7847986,3.5901329,1.6833872,3.4240479,1.8372175,0.0000000,2.5701453,3.6551315,4.0327091,3.8781182)
  
  data <- reactive({
    df1 <- data.frame(value = val1)   
    df2 <- data.frame(value = val2)   
    
    data_df <- bind_rows(lst(df1, df2), .id = 'id')
  })
 
  
  mydata <- reactive({
    req(input$submit)
    
    if(input$log2 == TRUE){
      data <- data()
      cols <- sapply(data, is.numeric)
      data[cols] <- lapply(data[cols], function(x) log2(x+1))
    
    }
    else{
      data <- data()
    }
    return(data)
  })
  
  
  v <- reactiveValues()
  observeEvent(input$show_plot, {
     v$plot <- hist_function(DF=mydata(), bins=input$bins, alpha=input$alpha)
  })
  
  output$histogram <- renderPlot({
    req(input$submit)
    if (is.null(v$plot)) return()
    v$plot
  })
  
}

shinyApp(ui = ui, server = server)

Note that if I put the actionButton when the tabsetPanel finishes, the actionButton works in Tab 3, but it appears in Tab 1, which I don't want. I only want to have the submit button in that tab.

ui <- fluidPage(
  
  titlePanel("My app"),
  
  sidebarLayout(
    sidebarPanel(
      tabsetPanel(
        
        tabPanel("Tab1",
                 checkboxInput("log2", "Log2 transformation", value = FALSE),
                 actionButton("submit", "Submit")
        ),
        
        tabPanel("Tab2",
                 sliderInput("bins",
                             "Number of bins:",
                             min = 1,
                             max = 50,
                             value = 10),
                 #actionButton("show_plot", "See the plot")
        ),
        
        tabPanel("Tab3",
                 numericInput("alpha", "Opacity of the histogram", value=0.2),
                 #actionButton("show_plot", "See the plot")
        )
        
      ),
      actionButton("show_plot", "See the plot") ### THIS IS THE NEW BUTTON
      
    ),
    
    mainPanel(
      plotOutput("histogram"),

    )
  )
)

image 2

On the other hand, I was thinking to create two different buttons... and therefore, I would have to add the new one to the observeEvent... but, I wanted to ask here just in case someone knows how to do it without creating a new button.

Thanks very much in advance

Regards


Solution

  • You can't have two or more inputs with the same IDs, but it doesn't mean you need to have two observEvents in your case.

    Change the ID of the second button:

    tabPanel("Tab3",
                     numericInput("alpha", "Opacity of the histogram", value=0.2),
                     actionButton("show_plot_2", "See the plot")
    

    And change the oberveEvent as below:

    observeEvent(input$show_plot | input$show_plot_2, {
        v$plot <- hist_function(DF=mydata(), bins=input$bins, alpha=input$alpha)
      })
    

    However, please note that now user can change number of bins, do not click the "see the plot" button, go to tab3, change the opacity, click "see the plot" and plot will be updated taking into account new number of bins and new opacity - take into account if this will be surprising for user or not. If you don't want this, then indeed you will need two observeEvents.

    I see that plot is displayed only if input$submit is clicked at least once in session, it looks strange for me, so I'm leaving this note :).