glin / reactable

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

reactableUpdate not preserving matrix dimensions #360

Open dleopold opened 7 months ago

dleopold commented 7 months ago

It looks like the updateReactable function does not properly preserve matrix dimensions. Here is a toy example:

library(shiny)
library(reactable)

ui <- fluidPage(
  reactableOutput("table"),
  actionButton("update", "Update table")
)

server <- function(input, output) {

  mx <- matrix(
    nrow = 8,
    ncol = 12,
    dimnames = list(
      LETTERS[1:8],
      1:12
    )
  )
  mx[,] <- sample(c(T,F), 8 * 12, replace = TRUE)

  output$table <- renderReactable({
    reactable(
      mx,
      rownames = TRUE,
      columns = list(
        .rownames = colDef(
          cell = function(value) {value}
        )
      )
    )
  })

  observeEvent(input$update, {
    mx[,] <- sample(mx, 8 * 12)
    print(dim(mx))
    updateReactable("table", data = mx)
  })

}
shinyApp(ui = ui, server = server)

simply changing the update call to: updateReactable("table", data = as.data.frame(mx)) seems to result in a correct update, but the documentation suggests that the data argument can accept a matrix.

Also, updating the matrix without the colDef specification for the .rownames column in the initial render function causes the row names to be dropped from the rendered table. This happens regardless of whether in input and/or update is a matrix or data.frame.

glin commented 6 months ago

Thanks for the report and repro. Internally, matrices are handled by just running as.data.frame() on them, and row names are done by appending them to the data frame as a new column. Both of these are missing from updateReactable(). Matrices should be fairly straightforward to fix but row names are trickier. updateReactable() might have to take a rownames argument as well, for lack of a way to know whether the original table had rownames. Or always add the row names, which isn't super ideal, hmm.