glin / reactable

Interactive data tables for R
https://glin.github.io/reactable
Other
627 stars 80 forks source link

Allow user to hide/show columns #319

Open royfrancis opened 1 year ago

royfrancis commented 1 year ago

Is there is mechanism to display few columns by default and leave it to the user to show more if needed?

This seems to be a nice implementation.

Screenshot from 2023-04-11 12-27-18

glin commented 1 year ago

Yes, there are two JavaScript API methods for this that were added in a recent version:

New Reactable.toggleHideColumn() and Reactable.setHiddenColumns() methods in the JavaScript API to toggle or set hidden columns. JavaScript render functions and style functions also receive a new state.hiddenColumns property for the hidden columns in the table. (https://github.com/glin/reactable/issues/246)

However, there's no built-in UI to do this, and another issue tracks the addition of a ColVis-like button: https://github.com/glin/reactable/issues/246

For now, there's only a simple example of using the JavaScript API to create your own column visibility toggle button at Column visibility toggle button example.

nick-youngblut commented 7 months ago

Does the Column visibility toggle button example work with Shiny?

I tried:

library(shiny)
library(reactable)
library(htmltools)
library(MASS)

ui <- fluidPage(
  tags$head(
    # Include custom JavaScript to manage column visibility
    tags$script(
      "Shiny.addCustomMessageHandler('toggleColumns', function(message) {
        Reactable.setHiddenColumns('cars-vis-table', prevColumns => {
          return prevColumns.length === 0 ? ['Passengers', 'DriveTrain', 'Cylinders', 'EngineSize'] : []
        });
      });"
    )
  ),
  actionButton("toggleBtn", "Show/hide more columns"),
  reactableOutput("carsTable")
)

server <- function(input, output, session) {
  data <- Cars93[1:5, c("Manufacturer", "Model", "Type", "Price",
                        "Passengers", "DriveTrain", "Cylinders", "EngineSize")]

  output$carsTable <- renderReactable({
    reactable(
      data,
      columns = list(
        Passengers = colDef(show = FALSE),
        DriveTrain = colDef(show = FALSE),
        Cylinders = colDef(show = FALSE),
        EngineSize = colDef(show = FALSE)
      ),
      elementId = "cars-vis-table"
    )
  })

  observeEvent(input$toggleBtn, {
    # Send a message to the JavaScript handler when the button is clicked
    session$sendCustomMessage('toggleColumns', NULL)
  })
}

shinyApp(ui, server)

...but I just got the warning:

Warning in renderWidget(instance) :
  Ignoring explicitly provided widget ID "cars-vis-table"; Shiny doesn't use them

...and the Show/hide more columns button does nothing.

nick-youngblut commented 7 months ago

I found a solution:

library(shiny)
library(reactable)
library(htmltools)
library(MASS)

showHideButton = function(id){
  tags$button(
    "Show/hide more columns",
    onclick = "Reactable.setHiddenColumns('cars-vis-table', prevColumns => {
        return prevColumns.length === 0 ? ['Passengers', 'DriveTrain', 'Cylinders', 'EngineSize'] : []
      })"
  )
}

ui <- fluidPage(
  showHideButton("toggleBtn"),
  reactableOutput("carsTable")
)

server <- function(input, output, session) {
  data <- Cars93[1:5, c("Manufacturer", "Model", "Type", "Price",
                        "Passengers", "DriveTrain", "Cylinders", "EngineSize")]

  output$carsTable <- renderReactable({
    reactable(
      data,
      columns = list(
        Passengers = colDef(show = FALSE),
        DriveTrain = colDef(show = FALSE),
        Cylinders = colDef(show = FALSE),
        EngineSize = colDef(show = FALSE)
      ),
      elementId = "cars-vis-table"
    )
  })

  observeEvent(input$toggleBtn, {
    # Send a message to the JavaScript handler when the button is clicked
    session$sendCustomMessage('toggleColumns', NULL)
  })
}

shinyApp(ui, server)