reactable
reactable copied to clipboard
Change cell styling based on multiple columns
Issue:
Using multiple columns as arguments to style a single column's cells.
Version: reactable_0.2.0
For this reprex I'm trying to use one column to create a bar length, and then color that bar according to a second column. Alternatively, this could be assigning say, bold face to a cell and then coloring it according to a secondary column, or some other combination of inputs to alter a single cell.
I was able to successfully use colDef to accomplish this, but had to rely on absolute position of the row within the dataset with the index argument.
Is there a better way to use multiple columns as arguments within a custom function? I tried to do this with JS via cellInfo.row['col_name'] but couldn't get that workflow to succeed - likely due to errors on my part.
library(dplyr)
library(reactable)
library(htmltools)
# Verbatim borrowed from your docs
bar_chart <- function(label, width = "100%", height = "14px", fill = "#00bfc4", background = NULL) {
bar <- div(style = list(background = fill, width = width, height = height))
chart <- div(style = list(flexGrow = 1, marginLeft = "6px", background = background), bar)
div(style = list(display = "flex", alignItems = "center"), label, chart)
}
mtcars %>%
select(cyl, mpg) %>%
arrange(cyl) %>%
# Just using this to find the specific placement of which rows to "cut" at
mutate(row_n = row_number()) %>%
reactable(
defaultPageSize = 20,
columns = list(
mpg = colDef(
name = "mpg",
defaultSortOrder = "desc",
cell = function(value, index) {
width <- paste0(value * 100 / max(mtcars$mpg), "%")
value <- format(value, big.mark = ",")
value <- format(value, width = 9, justify = "right")
# Relying on absolute position rather than matching logic
# I don't know if it's possible to reference multiple columns here
# my understanding is that the mpg col is passed through, but nothing else
color_fill <- if(index < 12) {
"blue"
} else if (index >= 12 & index <=18) {
"yellow"
} else {
"red"
}
bar_chart(value, width = width, fill = color_fill)
},
align = "left",
style = list(fontFamily = "monospace", whiteSpace = "pre")
)
)
)

Created on 2020-07-03 by the reprex package (v0.3.0)
In an R render function or style function, you can use the row index argument to get the other values in the row. For a really simplified example:
library(reactable)
data <- mtcars[, c("cyl", "mpg")]
reactable(
data,
columns = list(
mpg = colDef(
cell = function(value, index) {
# Get the cyl value from the same row
cyl <- data$cyl[index]
sprintf("%s (cyl=%s)", value, cyl)
},
style = function(value, index) {
cyl <- data$cyl[index]
if (cyl == 6) {
list(fontWeight = "bold")
}
}
)
)
)

In a JavaScript render or style function, the equivalent would be using cellInfo.row to get other values in the row:
library(reactable)
data <- mtcars[, c("cyl", "mpg")]
reactable(
data,
columns = list(
mpg = colDef(
cell = JS("function(cellInfo) {
// Get the cyl value from the same row
const cyl = cellInfo.row.cyl
return cellInfo.value + ' (cyl=' + cyl + ')'
}"),
style = JS("function(cellInfo) {
if (cellInfo.row.cyl === 6) {
return { fontWeight: 'bold' }
}
}")
)
)
)
I think your example is really close - you just have to assign the data to a variable so you can access it. Here's my slightly modified example:
library(dplyr)
library(reactable)
library(htmltools)
bar_chart <- function(label, width = "100%", height = "14px", fill = "#00bfc4", background = NULL) {
bar <- div(style = list(background = fill, width = width, height = height))
chart <- div(style = list(flexGrow = 1, marginLeft = "6px", background = background), bar)
div(style = list(display = "flex", alignItems = "center"), label, chart)
}
data <- mtcars %>%
select(cyl, mpg) %>%
arrange(cyl)
reactable(
data,
defaultPageSize = 20,
columns = list(
mpg = colDef(
name = "mpg",
defaultSortOrder = "desc",
cell = function(value, index) {
width <- paste0(value * 100 / max(mtcars$mpg), "%")
value <- format(value, big.mark = ",")
value <- format(value, width = 9, justify = "right")
# Color based on the row's cyl value
cyl <- data$cyl[index]
color_fill <- if (cyl == 4) {
"blue"
} else if (cyl == 6) {
"yellow"
} else {
"red"
}
bar_chart(value, width = width, fill = color_fill)
},
align = "left",
style = list(fontFamily = "monospace", whiteSpace = "pre")
)
)
)
Since this is pretty common to do when making tables, I've added an example of accessing data from other columns using both R and JS: https://glin.github.io/reactable/articles/cookbook/cookbook.html#show-data-from-other-columns
In an R render function or style function, you can use the row index argument to get the other values in the row.
@glin Is there a way to use the column index as well?
@Johan-rosa Not exactly, but there is a column name/ID available as an optional 3rd argument that you could use directly, or use to get the column index. Check out the Cells - R render function docs.