Search code examples
rr-markdownreactable

Conditional Formatting with Reactable and Blogdown


Using R's Reactable package and RMarkdown I want to create a table where a column has a green square for Status <= 2 and a red square otherwise.

If I try to format the Status column based on it's value, it creates a non-colored square. See image.

enter image description here

In the .Rmd file below, I can get the css to make a colored square in a column only if the column has no values.

To summarize, under the Status column, I'd like colored squares (green square for Status <= 2 and a red square otherwise) with no visible numbers, left aligned with the Status name of the column.

The Flag column is there just to show that the css is working.

RMarkdown File

title: Conditional Colored Square in Reactable Table
author: IX
date: 'September 5, 2020'
slug: test
categories: []
tags: []
output: 
  html_document
---

```{css, echo=FALSE}
 .row {
    display : flex;
    align-items : center;
    margin-bottom: 15px;
  }
.box {
  height: 20px;
  width: 20px;
  border: 1px solid black;
  margin-right : 5px;
}

.red {
  background-color: red;
}

.green {
  background-color: green;
}

.blue {
  background-color: blue;
}
```



```{r, echo=FALSE, message=FALSE, warning=FALSE}
library("reactable")

orders <- data.frame(
  Order = 2300:2304,
  Created = seq(as.Date("2019-04-01"), by = "day", length.out = 5),
  Customer = sample(rownames(MASS::painters), 5),
  Status = c(1, 2, 3, 4, 5),
  Flag = c("", "", "", "", "")
)

reactable(orders, columns = list(
  Status = colDef(cell = function(value) {
    if (value <= 2) {
      class <- paste0("tag box green", tolower(value))
      htmltools::div(class = class, value)
    }
  }),
  Flag = colDef(cell = function(value) {
    class <- paste0("tag box green", tolower(value))
    htmltools::div(class = class, value)
  })  
))

Solution

  • Using css is the right way to go.

    The color doesn't appear in the example you provided because of the paste:

    class <- paste0("tag box green", tolower(value))
    

    which results in green1, green2, ... that are undefined selector classes.

    Try:

    ---
    title: Conditional Colored Square in Reactable Table
    author: IX
    date: 'September 5, 2020'
    slug: test
    categories: []
    tags: []
    output: 
      html_document
    ---
    
    ```{css, echo=FALSE}
    .row {
        display : flex;
        align-items : center;
        margin-bottom: 15px;
      }
    .box {
      height: 20px;
      width: 20px;
      border: 1px solid black;
      margin-right : 5px;
    }
    
    
    .green {
      background: green;
      color: green;
    }
    
    .red {
      background-color: red;
      color: red;
    }
    ```
    
    
    
    ```{r, echo=FALSE, message=FALSE, warning=FALSE}
    library("reactable")
    
    orders <- data.frame(
      Order = 2300:2304,
      Created = seq(as.Date("2019-04-01"), by = "day", length.out = 5),
      Customer = sample(rownames(MASS::painters), 5),
      Status = c(1, 2, 3, 4, 5),
      Flag =  c("", "", "","","")
    )
    
    reactable(orders, columns = list(
      Status = colDef(cell = function(value) {
        if (value <= 2) {
          class <- "box green"
        } else {
          class <- "box red"
        }
        htmltools::div(class = class, "")  
      }),
      Flag = colDef(cell = function(value) {
          class <- paste0("tag box")
          htmltools::div(class = class, value)
      })  
    ))
    

    enter image description here