Sebastian Zeki
Sebastian Zeki

Reputation: 6874

How to download datatable after editing in shiny

I have about 20 thousand images in a datatable in a shiny application. I want to delete images I dont like and then download the resulting datatable (just with pathnames to the images I want).

I have managed to see a dataframe with each row showing me an image. I can delete rows I dont like. I'd like now to be able to download the dataframe (just with the paths of the files rather than the actual images) into a csv. I don't seem to be able to do this using the downloadHandler. What am I missing?

Here is my code:

server.R

library(shiny)
library(shinydashboard)
library(data.table)
library(DT)
server<-shinyServer(function(input, output) {
  vals<-reactiveValues()
  vals$Data<-data.table(
    df
  )

  output$MainBody<-renderUI({
    fluidPage(
      box(width=12,
          hr(),

          column(12,dataTableOutput("Main_table")),
          tags$script(HTML('$(document).on("click", "input", function () {
                           var checkboxes = document.getElementsByName("row_selected");
                           var checkboxesChecked = [];
                           for (var i=0; i<checkboxes.length; i++) {
                           if (checkboxes[i].checked) {
                           checkboxesChecked.push(checkboxes[i].value);
                           }
                           }
                           Shiny.onInputChange("checked_rows",checkboxesChecked);
  })')),
      tags$script("$(document).on('click', '#Main_table button', function () {
                  Shiny.onInputChange('lastClickId',this.id);
                  Shiny.onInputChange('lastClick', Math.random())
});")

      )
      )
    })



  output$downloadData <- downloadHandler(
    filename = function() {
      paste(input$Main_table, ".csv", sep = "")
    },
    content = function(file) {
      write.csv(vals$Data, file, row.names = FALSE)
    }
  )

  output$Main_table<-renderDataTable({
    DT=vals$Data
    datatable(DT,
              escape=F)}
      )


})

ui.R

ui<-fluidPage(dashboardHeader(disable = T),
                  dashboardSidebar(disable = T),
                  downloadLink("downloadData", "Download"),
                  dashboardBody(uiOutput("MainBody")

                  )
)
# Run the application
shinyApp(ui = ui, server = server)

Upvotes: 0

Views: 420

Answers (1)

ismirsehregal
ismirsehregal

Reputation: 33397

The problem is that df is a function from library(stats). Please see ?df. Please, never use df as a variable name - this only causes confusion; take DF instead. You wrapped this function into data.table() and passed it into a reactiveValue (see the print() I added).

This construct is treated as a list() by write.csv() and it doesn't know what do do with a list() causing the following error:

Error in write.table: unimplemented type 'list' in 'EncodeElement'

Accordingly you might want to fix your data.table initialization by e.g. passing NULL instead of df:

library(shiny)
library(shinydashboard)
library(data.table)
library(DT)

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

  vals <- reactiveValues(myTabData = data.table(NULL))
  vals$Data <- data.table(df)

  print(paste("myData:", isolate(vals$Data)))

  output$MainBody <- renderUI({
    fluidPage(box(
      width = 12,
      hr(),

      column(12, dataTableOutput("Main_table")),
      tags$script(
        HTML(
          '$(document).on("click", "input", function () {
                           var checkboxes = document.getElementsByName("row_selected");
                           var checkboxesChecked = [];
                           for (var i=0; i<checkboxes.length; i++) {
                           if (checkboxes[i].checked) {
                           checkboxesChecked.push(checkboxes[i].value);
                           }
                           }
                           Shiny.onInputChange("checked_rows",checkboxesChecked);})'
        )
      ),
      tags$script(
        "$(document).on('click', '#Main_table button', function () {
                  Shiny.onInputChange('lastClickId',this.id);
                  Shiny.onInputChange('lastClick', Math.random())});"
      )

    ))
  })



  output$downloadData <- downloadHandler(
    filename = function() {
      "Main_table.csv"
    },
    content = function(file) {
      write.csv(vals$myTabData, file, row.names = FALSE)

      # Warning: Error in write.table: unimplemented type 'list' in 'EncodeElement'
      # write.csv(vals$Data, file, row.names = FALSE)
    }
  )

  output$Main_table <- renderDataTable({
    DT = vals$Data
    datatable(DT, escape = FALSE)
  })


})

ui <- fluidPage(
  dashboardHeader(disable = T),
  dashboardSidebar(disable = T),
  downloadLink("downloadData", "Download"),
  dashboardBody(uiOutput("MainBody"))
)

shinyApp(ui = ui, server = server)

Furthermore you should fix your filename (input$Main_table is not existing)

Upvotes: 1

Related Questions