Home > Back-end >  Shiny: Show Download Button Only If An Action Button Is Pressed
Shiny: Show Download Button Only If An Action Button Is Pressed

Time:01-08

I have a reactive data frame df1(). A user can add their initials as text inputs such that the text is filled to rows as a new column name when the user clicks the Add button.

Everything works fine but I would like to add one more thing:

Make the download button download show only if the action button bttn1 is pressed. Currently download is shown regardless of pressing bttn1.

I can't understand why the following is not working:

  observe({
    if (is.null(input$bttn1)) {shinyjs::hide("download")}
    else {shinyjs::show("download")}
  })

The following is a fully working code:

##### ui
ui <- dashboardPage(
  skin = "black",
  
  #### Upper navigation bar
  dashboardHeader(
    title = "title",
    titleWidth = 230
  ),
  
  
  #### Side bar
  dashboardSidebar(disable = T),
  
  
  #### Body
  dashboardBody(
    shinyjs::useShinyjs(),
    
    tabsetPanel(
      tabPanel(
        
        ### tab1
        tabName = "tab1", 
        h5("Tab 1"),
        
        fluidRow(
          
          reactableOutput("table1"),
          
          textInput("textinput1", "Initials:"),
          actionButton("bttn1", "Add", class = "btn-primary"),
          
          reactableOutput("table2"),
          uiOutput("ui_download")
          
        ) # fluidRow
      ), # tabPanel
      
      
      #### tab2
      tabPanel(
        tabName = "tab2", 
        h5("Tab 2"),
        
        fluidRow(
          
        ) # fluidRow
      ) # tabPanel
    ) # tabsetPanel
    
    
  ) # dashboardBody
) # dashboardPage


#### server 
server <- function(input, output, session) {
  
  ## df1
  # reactive
  df1 <- reactive({
    data.frame(
      "id" = c("A", "A", "A", "A"),
      "num1" = c(10, 11, 12, 13)
    )
  })
  
  # renderReactable
  output$table1 <- renderReactable({
    reactable(df1(), borderless = F, defaultColDef = colDef(align = "center"))
  })
  
  ## df2
  ## Text input 
  rv1 <- reactiveValues()
  
  observe({
    if (nrow(df1()) == 0) {shinyjs::hide("bttn1")} 
    else {shinyjs::show("bttn1")}
  })
  
  observe({
    if (nrow(df1()) == 0) {shinyjs::hide("textinput1")} 
    else {shinyjs::show("textinput1")}
  })
  
  observeEvent(input$bttn1, {
    rv1$values <- df1()
    rv1$values$name <- input$textinput1
  })
  
  rv1_text <- reactive({
    rv1$values
  })
  
  output$table2 <- renderReactable({
    req(rv1_text())
    reactable(rv1_text(), borderless = F, defaultColDef = colDef(align = "center"))
  })
  
  ## downloadButton
  # renderUI
  output$ui_download <- renderUI({
    # req(rv1_text())
    downloadButton("download", "Download")
  })
  
  **# Why isn't this working?**
  observe({
    if (is.null(input$bttn1)) {shinyjs::hide("download")}
    else {shinyjs::show("download")}
  })
  
  # Download csv
  output$download <- downloadHandler(
    filename = function() {
      paste0('data', '.csv')
    },
    
    content = function(file) {
      write.csv(rv1_text(), file, row.names = F)
    }
  )
  
}

shinyApp(ui, server)

CodePudding user response:

I couldn't run your codes since you did not share the libraries you used in. But If I understand you correctly, conditionalPanel is very suitible for your purpose.

Here is a small shiny app that you can adapt it to your codes:

library(shiny)

ui <- fluidPage(
  actionButton("call_download", "Show Download Button"),


conditionalPanel(condition = "input.call_download == 1",
            downloadLink('downloadData', 'Download')
                )
 )

server <- function(input, output) {


output$downloadData <- downloadHandler(
   filename = function() {
     paste('data-', Sys.Date(), '.csv', sep='')
   },
   content = function(con) {
     write.csv(mtcars, con)
   } )

}


shinyApp(ui, server)
  • Related