reactable icon indicating copy to clipboard operation
reactable copied to clipboard

show/hide column

Open aha-incom opened this issue 3 years ago • 6 comments

Hi, would it be possible to update the "show" state of a column when calling reactable::updateReactable.

I know that I can re-render the table by making the output$table reactive on some input or reactive values but I would like to avoid a re-render.

Thanks for the awesome package by the way!

library(dplyr)
library(reactable)
library(magrittr)
library(shiny)

data <- 
  dplyr::tibble(
    x = 1:10,
    y = rnorm(10),
    extra_column = rnorm(10, 20, 5)
  )
  
shinyApp(
  ui = fluidPage(
    shiny::actionButton("action", "Some Action"),
    column(4, reactable::reactableOutput("table"))
    # )
  ),
  server = function(input, output) {
    
    output$table <- reactable::renderReactable({
      
      reactable::reactable(data,
                           columns = list(
                             extra_column = colDef(show = FALSE)
                           ))
      
      
    })
    
    observeEvent(input$action, {
      reactable::updateReactable("table",
                                 data = data %>% dplyr::mutate(y = rnorm(10)))
      # Here goes some neat code that update the "extra_column" from show = FALSE to show = TRUE.
    })
    
  }
)

aha-incom avatar Aug 25 '21 07:08 aha-incom

Hi, this isn't possible today, but it's a good idea. I'm not sure what the API would look like -- show is a column option, so a updateReactable(columns = list(...)) argument was my initial thought, but it sounds painful to have to specify all your column definitions again. Maybe a separate argument like updateReactable(visibleColumns = c("vector", "of", "columns")) makes more sense.

glin avatar Sep 05 '21 01:09 glin

Cool, that sounds awesome! The DataTable package have this functionality DT::showCols if this can give some ideas/inspiration.

aha-incom avatar Sep 06 '21 10:09 aha-incom

Thank´s for this amazing package first - it really shines among all other pkgs out there (functionality, docs, ease of use, ...) It´s just outstanding 👏 I would love to see this feature too - DT has a plugin that enables just that.

As the columns parameter can be stored in a variable the updateReactable(columns = list(...))-idea seems to me valid:

library(shiny)
library(reactable)

ui <- fluidPage(
  tagList(
    checkboxInput("showX", "show column x"),
    reactableOutput("table")
  )
)

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

  columns <- list(
    x = colDef(show = FALSE)
  )
  
  output$table <- renderReactable(
    reactable(
      data.frame(x = c(1:5), y = c(1:5)), 
      columns
    )
  )

  observeEvent(
    input$showX, 
    {
      columns$x$show <- input$showX
      updateReactable("table", columns = columns)
    }, 
    ignoreInit = TRUE
  )
}

shinyApp(ui, server)

markschat avatar Apr 04 '22 10:04 markschat

Is there any workaround with custom JavaScript before this is implemented @glin ?

novotny1akub avatar Aug 08 '22 10:08 novotny1akub

Just wanted to bump this thread to see if there is any progress on client side manipulation of the show/hide state of a column. Perhaps it would be possible to allow the show parameter in colDef to optionally accept a JS function that would take colInfo and state as inputs and return true/false to make the value dynamic based on table data or metadata. Not sure how difficult this would be, but it would be a very welcomed addition to an already amazing package.

dleopold avatar Mar 07 '23 13:03 dleopold

I just noticed that Reactable.setHiddenColumns() is avaiable in the reactable (v0.4.0+) JavaScript API . For shiny apps this means we can control which columns are hidden by adding a custom message handler. In case it helps anyone else who comes across this thread, here is my first attempt at a toy example.

in custom.js:

$( document ).ready(function(){
  Shiny.addCustomMessageHandler('hideCols', function(params) {
    Reactable.setHiddenColumns(params.id, params.cols)
  });
});

in app.R:

library(shiny)
library(reactable)

hideCols <- function(id, cols, session = getDefaultReactiveDomain()) {
  session$sendCustomMessage("hideCols", list(id = id, cols = cols))
}

ui <- fluidPage(
  includeScript(path = "custom.js"),
  checkboxInput("hidden","Hide Column"),
  reactableOutput("rtab")
)

server <- function(input, output) {
  
  # Render initial table
  output$rtab <- renderReactable({ 
    data.frame(
      Character=LETTERS[1:10],
      Number=seq(1,100, by=10),
      Invisible="HIDEME"
    ) |>
      reactable() 
  })
  # Observe checkbox input
  observeEvent(input$hidden, ignoreInit = T, {
    if(input$hidden){
      cols <- "Invisible"
    }else{
      cols <- ""
    }
    hideCols('rtab', as.list(cols))
  })
}

shinyApp(ui = ui, server = server)

In my current real world applications I would have the hideCols function react to changes in the data being passed to updateReactable(). However, I would be interested to see a solution where an update to the data could trigger a call to Reactable.setHiddenColumns() on the client and use the content of the data to conditionally hide columns (e.g. if all values are empty).

dleopold avatar Mar 07 '23 18:03 dleopold