Search code examples
rinputshinyexportreactive

Shiny: How to export table with both selectInput and manual input


I want to create a table that will take values from both selectizeInput and manual input. And then export to CVS. I have the table ready but when I tried to export(click on "CVS") it won't take the changes made by manual input. Below is an example of it. How to make the csv export take both selectizeInput and manual input? I also feel my code is a bit superfluous. Is there a simplified way to create the table? Thanks!

library(shiny)
library(shinydashboard)
library(DT)

ui <- dashboardPage(
  dashboardHeader(title = "test"),
  dashboardSidebar(),
dashboardBody(shiny::selectizeInput(inputId = "apple_lbs_filter",
                                    label = "Apple lbs",
                                    choices = c(1:10)),
              shiny::selectizeInput(inputId = "cherry_lbs_filter",
                                    label = "Cherry lbs",
                                    choices = c(1:10)),
              shiny::selectizeInput(inputId = "pineapple_lbs_filter",
                                    label = "Pineapple lbs",
                                    choices = c(1:10)),
              shiny::selectizeInput(inputId = "pear_lbs_filter",
                                    label = "Pear lbs",
                                    choices = c(1:10)),
              DT::DTOutput("fruit"),
              shiny::actionButton(inputId = "update_lbs",label = "Update lbs"),
              
              shiny::downloadButton(outputId = "export",label = "CSV"))
)

server <- function(input, output, session) {

  fruit_df <- shiny::reactiveValues()
  fruit_df$df <- data.frame(fruit_name = c("apple","cherry","pineapple","pear"),
                            fruit_lbs = c(2,5,6,3))  
  
  output$fruit <- DT::renderDT({
      DT::datatable(fruit_df$df,editable = TRUE)
    })
  
  lbs_newentry <- shiny::observe({
    if(input$update_lbs > 0) {
      lbs_newline <- shiny::isolate(c(
        input$apple_lbs_filter,
        input$cherry_lbs_filter,
        input$pineapple_lbs_filter,
        input$pear_lbs_filter
      ))
      shiny::isolate(fruit_df$df <- cbind(fruit_name = c("apple",
                                               "cherry",
                                               "pineapple",
                                               "pear"),
                                       fruit_lbs = lbs_newline))
    }
  })
  
  
  
  output[["export"]] <- shiny::downloadHandler(
    filename = function(){paste("fruit",Sys.Date(),".csv")},
    content = function(file){
      write.csv(fruit_df$df,file,row.names = FALSE)
    }
  )
}

shinyApp(ui, server)

Solution

  • This is only a partial answer, because I've removed the selectizeInput() to try and condense the code per your request to simplify. Editing of the table can be done directly in the table. Additionally, I added the buttons extension to directly download the table as a csv. Hopefully this is helpful.

    library(shiny)
    library(shinydashboard)
    library(DT)
    
    ui <- dashboardPage(
      dashboardHeader(title = "test"),
      dashboardSidebar(),
      dashboardBody(h6("Table is editable"),
                    DT::DTOutput("fruit", width = "400px"))
    )
    
    server <- function(input, output, session) {
      fruit_df <- reactiveValues("df" = data.frame(fruit_name = c("apple","cherry","pineapple","pear"),
                                                         fruit_lbs = c(2,5,6,3))  )
      
      output$fruit <- DT::renderDT({
        DT::datatable(fruit_df$df, editable = T,
                      extensions = 'Buttons', #Extra functions for the table
                      options = list("dom" = 'T<"clear">lBfrtip',
                                     buttons = "csv"
                      )
        )
      })
    
    }
    
    shinyApp(ui, server)