rshinyreactable

Remove all/none checkbox from Reactable table in Shiny app


I wish to remove the all/none checkbox from a Reactable table used in a Shiny app. For a regular R script, an answer was suggested here.

However this solution fails with:

Warning in renderWidget(instance) : Ignoring prepended content; prependContent can't be used in a Shiny render call

The code below fails to remove the checkbox with the error mentioned above. So, how do I remove the all/none checkbox of a Reactable table in a Shiny app.

library(reactable)
library(htmlwidgets)

javascript <- JS('
document.querySelector(\'.rt-select-input[aria-label="Select all rows"]\').parentElement.parentElement.style.display="none";
')


ui <- fluidPage(reactableOutput("table")
)

server <- function(input, output, session) {
  output$table <- renderReactable({
    e <- reactable(iris,
              onClick = "select",
              selection = "multiple") 
    (p <- prependContent(e, onStaticRenderComplete(javascript)))
    })
}  
shinyApp(ui, server)  

Solution

  • This can be achieved by a sneaky workaround using shiny's javascript events and the shinyjs package.

    NOTE :

    I tried the shiny:value event but it didn't work it supposedly should've been executed whenever the output component is rendered but sadly it didn't.

    library(reactable)
    library(shiny)
    library(shinyjs)
    # you'll need to pass the id that you provided to reactableOutput(id)
    js.code <- '
    shinyjs.hideSelectAll = function(id){
        $("#"+id).on("shiny:visualchange", function({currentTarget}) {   
            currentTarget = currentTarget.querySelector(".rt-select-input[aria-label=\'Select all rows\']")
            if(currentTarget) currentTarget.parentElement.parentElement.style.display="none";
        });
    } 
    '
    
    ui <- fluidPage(reactableOutput("table"),
        useShinyjs(debug=TRUE),
        extendShinyjs(text = js.code, functions = c("hideSelectAll"))
    )
    
    server <- function(input, output, session) { 
      output$table <- renderReactable({ 
        reactable(iris,
                  onClick = "select",
                  selection = "multiple")
        })
        js$hideSelectAll("table")
        delay(100, runjs('$( "#table" ).trigger( "shiny:visualchange" );'))
        
        #runjs('$( "#table" ).trigger( "shiny:visualchange" );')
    }  
    shinyApp(ui, server)  
    

    If you're going to use it one time

    library(reactable)
    library(shiny)
    library(shinyjs)
    js.code <- '
    document.querySelector(\'.rt-select-input[aria-label="Select all rows"]\').parentElement.parentElement.style.display="none";
    '
    
    ui <- fluidPage(reactableOutput("table"),
        useShinyjs(debug=TRUE)
    )
    
    server <- function(input, output, session) { 
      output$table <- renderReactable({ 
        reactable(iris,
                  onClick = "select",
                  selection = "multiple")
        })
        delay(100, runjs(js.code))
        
    }  
    shinyApp(ui, server) 
    

    Using only shiny with no external dependency:

    Even refreshing the data doesn't show the select all button. it appears that my first code isn't optimal :( but I'm leaving it as a reference.

    
    ui <- fluidPage(reactableOutput("table"),
        actionButton("button", "refresh"),
        tags$head(tags$script(HTML('
                setTimeout(()=>{
                    document.querySelector(\'#table .rt-select-input[aria-label="Select all rows"]\').parentElement.parentElement.style.display="none";
                }, 200)
        ')))
    )
    
    server <- function(input, output, session) { 
      output$table <- renderReactable({ 
        reactable(iris,
                  onClick = "select",
                  selection = "multiple")
        })
        observeEvent(input$button, {
        output$table <- renderReactable({ 
        reactable(mtcars,
                  onClick = "select",
                  selection = "multiple")
            })
        })
    }  
    shinyApp(ui, server)