'How to add fileInputs into DT

I need to add a fileInputs to each row of a table. Unfortunately, this widget does not work correctly, unlike regular actionButtons and other elements. The window for selecting a file is called, but the file is not loaded. I will be grateful for your help. Below is a simplified example application.

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

# Define UI for application that draws a histogram
ui <- fluidPage(DTOutput('tbl'))

# Define server logic required to draw a histogram
server <- function(input, output) {
    output$tbl = renderDataTable({
        DT <- iris
        
        for (i in 1:nrow(DT)) {
            DT$file <- as.character(fileInput(
                paste0("file", i),
                label = NULL,
                multiple = F,
                accept = c(
                    "text/csv",
                    "text/comma-separated-values,text/plain",
                    ".csv"
                ),
                buttonLabel = paste("File", i)
            ))
        }
        
        datatable(DT,
                  options = list(lengthChange = FALSE),
                  escape = FALSE,
                  selection = "single"
        )
    })
    
    lapply(paste0("file", 1:nrow(iris)), function(nm) {
        observeEvent(input[[ nm ]], {
            print(input[[ nm ]])
            
        })
    })
    
}

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


Solution 1:[1]

Indeed, as noted by HubertL, you have the same ids. That's because your loop is overwriting. Try this:

    DT <- iris
    DT$file <- character(nrow(DT))
    
    for (i in 1:nrow(DT)) {
        DT$file[i] <- as.character(fileInput( # added [i]
            paste0("file", i),
            label = NULL,
            multiple = F,
            accept = c(
                "text/csv",
                "text/comma-separated-values,text/plain",
                ".csv"
            ),
            buttonLabel = paste("File", i)
        ))
    }

If that still doesn't work, that's because you have to bind the file inputs:

    datatable(DT,
              options = list(
                lengthChange = FALSE,
                preDrawCallback = JS('function() { Shiny.unbindAll(this.api().table().node()); }'),
                drawCallback = JS('function() { Shiny.bindAll(this.api().table().node()); } ')
              ),
              escape = FALSE,
              selection = "single"
    )

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Stéphane Laurent