Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to give column total in footer of table with grouped rows using Javascript? #50

Closed
rdatasculptor opened this issue Jun 16, 2020 · 3 comments

Comments

@rdatasculptor
Copy link

First of all, thank you very much for this brilliant package! It surely has given my dashboards a boost.

I did not intend to cross post this issue, but I really would like to have a solution: https://stackoverflow.com/q/62393123/1983395
Maybe it's my lack of javascript knowledge, but I tried several things, with no luck.

@glin
Copy link
Owner

glin commented Jun 17, 2020

Hi,

Questions like this are definitely welcome here. This was an oversight in documentation -- the custom rendering docs don't mention what colInfo.data looks like when you have grouped/nested data: https://glin.github.io/reactable/articles/custom-rendering.html#footers

Usually, data will be an array of individual row data objects, like

{
  "Manufacturer": "Acura",
  "Model": "Integra",
  "Type": "Small",
  "Price": 15.9
}

However, when a row is aggregated, the individual sub row data will be nested under a _subRows property:

// For an aggregated row with 2 sub rows
{
  "Manufacturer": "Acura",
  "_subRows": [
    {
      "Manufacturer": "Acura",
      "Model": "Integra",
      "Type": "Small",
      "Price": 15.9
    },
    {
      "Manufacturer": "Acura",
      "Model": "Legend",
      "Type": "Midsize",
      "Price": 33.9
    }
  ]
}

You can insert a console.log(colInfo) in the JS function to explore the full data structure in your browser's JavaScript console:

footer = JS("function(colInfo) {
  console.log(colInfo)
}")

Since the individual row data is now nested, it's a little more work to sum it all up, but here's one method that uses two forEach loops:

library(reactable)

data <- MASS::Cars93[1:20, c("Manufacturer", "Model", "Type", "Price")]

reactable(
  data,
  groupBy = "Manufacturer",
  searchable = TRUE,
  columns = list(
    Price = colDef(
      aggregated = JS("function(cellInfo) {
        // Calculate sum of all values in visible rows
        var values = cellInfo.subRows.map(function(row) { return row.Price})
        var total = values.reduce(function(a, b) { return a + b }, 0)
        return total.toFixed(1)
      }"),
      footer = JS("function(colInfo) {
        var total = 0
        colInfo.data.forEach(function(row) { 
          row._subRows.forEach(function(data) { 
            total += data[colInfo.column.id]
          })
        })
        return '$' + total.toFixed(2)
      }")
    ),
    Manufacturer = colDef(footer = "Total")
  ),
  defaultColDef = colDef(footerStyle = list(fontWeight = "bold"))
)

I'll fix up the docs and probably add an example like this somewhere.

@rdatasculptor
Copy link
Author

Hi Glin,

This solved it perfectly for me! Thank you so much.
(If you please, ofcourse, you can copy paste this answer to stackoverflow)

For now I'll close this issue here.

@glin
Copy link
Owner

glin commented Jun 29, 2020

While adding this example to the docs, I found a slightly nicer way to do this. If you use an aggregate function rather than an aggregated renderer, the aggregated total will show up in the row data:

{
  "Manufacturer": "Acura",
  "Price": 49.8,
  "_subRows": [...]
}

Then you can just sum up the row values as usual. You don't have to get into the sub rows:

library(reactable)

data <- MASS::Cars93[1:20, c("Manufacturer", "Model", "Type", "Price")]

reactable(
  data,
  groupBy = "Manufacturer",
  columns = list(
    Manufacturer = colDef(footer = "Total"),
    Price = colDef(
      aggregate = "sum",
      footer = JS("function(colInfo) {
        var total = 0
        colInfo.data.forEach(function(row) {
          total += row[colInfo.column.id]
        })
        return '$' + total.toFixed(2)
      }")
    )
  ),
  defaultColDef = colDef(footerStyle = list(fontWeight = "bold"))
)

https://glin.github.io/reactable/articles/cookbook/cookbook.html#totals-with-aggregated-rows

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants