'Creating custom rendered footer values i a reactable

I am having a hard time to render my footer column in a reactable. I want to use JS here to access the client-side filtered state, and since iam not too familiar with JS i am stuck. What i want is: to use the summarized footer values from two columns to create a summarized footer value for a third column. See example below.

library(shiny)
library(tidyverse)

data = tibble(article =c("a", "b", "c"), sales = c(12,34,16), margin = c(6,20,9)) %>%
  mutate(profit = round(margin / sales * 100, digits = 2))

ui = fluidPage(
  
  div(style = "margin-top: 50px; display: flex; justify-content: center;",
  reactableOutput(outputId = "table"))
  
)

server = function(input, output, session){
 
  output$table = renderReactable({
    reactable(
    data = data,
    columns = list(
      article = colDef(
        footer = "..."),
      sales = colDef(
        format = colFormat(suffix = "€"),
        footer = JS("function(colInfo) {
        var total = 0
        colInfo.data.forEach(function(row) {
        total += row[colInfo.column.id]
        })
        return total.toFixed(2) + '€'}")),
      margin = colDef(
        format = colFormat(suffix = "€"),
        footer = JS("function(colInfo) {
        var total = 0
        colInfo.data.forEach(function(row) {
        total += row[colInfo.column.id]
        })
        return total.toFixed(2) + '€'}")),
      profit = colDef(
        format = colFormat(suffix = "%"),
        footer = "35/62*100"
      )
    ))
  })
   
}
shinyApp(ui, server)


Solution 1:[1]

Solution from the reactable developer here

Here's an example of a footer render function that uses colInfo.data. It's like the custom aggregate function example in the docs, except colInfo.data takes the place of rows.

library(reactable)
library(dplyr)

set.seed(10)

data <- sample_n(MASS::Cars93[23:40, ], 30, replace = TRUE) %>%
  mutate(Price = Price * 3, Units = sample(1:5, 30, replace = TRUE)) %>%
  mutate(Avg.Price = Price / Units) %>%
  select(Model, Manufacturer, Price, Units, Avg.Price)

reactable(
  data,
  groupBy = "Manufacturer",
  columns = list(
    Price = colDef(aggregate = "sum"),
    Units = colDef(aggregate = "sum"),
    Avg.Price = colDef(
      # Calculate the aggregate Avg.Price as `sum(Price) / sum(Units)`
      footer = JS("function(colInfo) {
        let totalPrice = 0
        let totalUnits = 0
        colInfo.data.forEach(function(row) {
          totalPrice += row['Price']
          totalUnits += row['Units']
        })
        return (totalPrice / totalUnits).toFixed(2)
      }")
    )
  )
)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 karel