glin / reactable

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

reactable footer total is doubled with paginateSubRows = TRUE and row is expanded #371

Open vneyman opened 2 months ago

vneyman commented 2 months ago

Total is doubled for each expanded row when paginateSubRows = TRUE. The below example will show a total of 956.2 vs 478.1. Is there a way to keep the footer total accurate. Maybe there is a javascript trick?

data <- MASS::Cars93[18:47, ] %>% select(Manufacturer, Model, Type, Sales = Price)

reactable( data, defaultExpanded = TRUE, paginateSubRows = TRUE, groupBy = "Manufacturer", searchable = TRUE, columns = list( Manufacturer = colDef(footer = "Total"), Sales = colDef( aggregate = "sum", format = colFormat(currency = "USD"), footer = JS("function(column, state) { let total = 0 state.sortedData.forEach(function(row) { total += row[column.id] }) return total.toLocaleString('en-US', { style: 'currency', currency: 'USD' }) }") ) ), defaultColDef = colDef(footerStyle = list(fontWeight = "bold")) )

glin commented 2 months ago

There is a way to tell if a row is grouped, but it's not well documented or obvious to use. A row will have a _subRows array property if it's grouped. You can ignore these rows, e.g.:

data <- MASS::Cars93[18:47, ] %>%
  select(Manufacturer, Model, Type, Sales = Price)

reactable(
  data,
  defaultExpanded = TRUE,
  paginateSubRows = TRUE,
  groupBy = "Manufacturer",
  searchable = TRUE,
  columns = list(
    Manufacturer = colDef(footer = "Total"),
    Sales = colDef(
      aggregate = "sum",
      format = colFormat(currency = "USD"),
      footer = JS("function(column, state) {
        let total = 0
        state.sortedData.forEach(function(row) {
          // Ignore grouped rows
          if (row._subRows) {
            return
          }
          total += row[column.id]
        })
        return total.toLocaleString('en-US', { style: 'currency', currency: 'USD' })
      }")
    )
  ),
  defaultColDef = colDef(footerStyle = list(fontWeight = "bold"))
)

This is included in a few examples on the custom rendering doc page, but it could definitely use better documentation.