Search code examples
rcheckboxshinydatatabledt

How to modify the following shiny code to obtain row indexes selected by checkbox?


I am interested to have a data table as following in my shiny app. After I select the rows using the check boxes, I would like to continue working on the selected data. The problem now is that I don't know how to get the index of the selected rows from this example. Can you please help?

I want to extend the following code which is given by this answer.

library(shiny)
library(DT)
runApp(list(
    ui = fluidPage(dataTableOutput("dtout")),
    server = function(input, output, session) {
        shinyInput <- function(FUN, id, num, ...) {
            inputs <- character(num)
            for (i in seq_len(num)) {
                inputs[i] <- as.character(FUN(paste0(id, i), label = NULL, ...))
            }
            inputs
        }
        
        output$dtout <- renderDataTable({
            datatable(
                cbind(
                    Pick = shinyInput(
                        checkboxInput,
                        "srows_",
                        nrow(mtcars),
                        value = NULL,
                        width = 1
                    ),
                    mtcars
                ),
                options = list(
                    drawCallback = JS(
                        'function(settings) {Shiny.bindAll(this.api().table().node());}'
                    )
                ),
                selection = 'none',
                escape = F
            )
        }, server = FALSE)
    }
))

I think it has to do with the callback function. But I couldn't figure it out.


Solution

  • If you would like to get the row indices where the checkbox is clicked, you can define a function which gets the value per id of the inputs

    shinyValue = function(id, len) {
        unlist(lapply(seq_len(len), function(i) {
            value = input[[paste0(id, i)]]
            if (is.null(value)) {
                NA
            }
            else {
                value
            }
        }))
    }
    

    and write these values into a data frame:

    df <- data.frame(isChecked = shinyValue('srows_', nrow(mtcars)))
    

    Then you get a list of these indices by using

    which(df$isChecked == TRUE)
    

    See this minimal example below:

    enter image description here

    library(shiny)
    library(DT)
    
    ui <- fluidPage(verbatimTextOutput("idxSelectedRows"),
                    dataTableOutput("dtout"))
    
    server <- function(input, output, session) {
        shinyInput <- function(FUN, id, num, ...) {
            inputs <- character(num)
            for (i in seq_len(num)) {
                inputs[i] <- as.character(FUN(paste0(id, i), label = NULL, ...))
            }
            inputs
        }
        
        shinyValue = function(id, len) {
            unlist(lapply(seq_len(len), function(i) {
                value = input[[paste0(id, i)]]
                if (is.null(value)) {
                    NA
                }
                else {
                    value
                }
            }))
        }
        
        output$idxSelectedRows <- renderPrint({
            df <- data.frame(isChecked = shinyValue('srows_', nrow(mtcars)))
            paste("Selected row indices: ",
                  paste(which(df$isChecked == TRUE), collapse = ", "))
        })
        
        output$dtout <- renderDataTable({
            datatable(
                cbind(
                    Pick = shinyInput(
                        checkboxInput,
                        "srows_",
                        nrow(mtcars),
                        value = NULL,
                        width = 1
                    ),
                    mtcars
                ),
                options = list(
                    drawCallback = JS(
                        'function(settings) {Shiny.bindAll(this.api().table().node());}'
                    )
                ),
                selection = 'none',
                escape = F
            ) 
        }, server = FALSE)
    }
    
    shinyApp(ui = ui, server = server)