I need to display a table in a Shiny app with the following requirements:
- app uses bslib themes (important because changes the css needed)
- table has conditional formatting (colours representing numeric values)
- the ability to select one or more rows in table
- when a row is selected, you can still see the conditional formatting
The default settings for datatable do not enable the last point - when you select a row, the selection colour is opaque and on top of the conditional formatting.
In contrast, a package like rhandsontable takes an excel-like approach where the selected row is indicated with a semi-transparent colour.
I can't use rhandsontable for other reasons, and I also cannot use the formattable package, because it (at present) converts numeric values into strings which prevents sorting the table by header correctly (see the github issue). So I am using DT's built-in conditional formatting functions (formatStyle, styleInterval).
Here's a minimal app that meets all the requirements, but there's something weird going on with the colour of the row selection and I'd like to understand it.
library(shiny)
library(dplyr)
ui <- bslib::page_fluid(
theme = bslib::bs_add_rules(
bslib::bs_theme(),
sass::as_sass("table.dataTable tbody tr.active td {
color: black !important;
box-shadow: inset 0 0 0 9999px rgba(255, 255, 0, 0.2) !important;}"
)),
DT::dataTableOutput("test_table")
)
server <- function(input, output, session) {
iris_small = iris %>% dplyr::slice_sample(n = 10)
output$test_table <- DT::renderDataTable({
cols_to_format <- c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")
# create 19 breaks and 20 rgb color values ranging from white to red
brks <- quantile(iris_small[cols_to_format], probs = seq(.05, .95, .05), na.rm = TRUE)
clrs <- round(seq(255, 40, length.out = length(brks) + 1), 0) %>%
{paste0("rgb(255,", ., ",", ., ")")}
iris_dt <- DT::datatable(
iris_small,
selection = 'multiple',
class = "hover row-border order-column compact nowrap",
)
iris_dt <- iris_dt %>%
DT::formatStyle(
cols_to_format,
target = "cell",
backgroundColor = DT::styleInterval(brks, clrs)
)
iris_dt
})
}
shinyApp(ui, server = server)
I have chosen to conditionally format the cells from white to red based on their value (guided by this example).
To change the colour of the selected row, I have used a bit of css guided by the kind person who answered a previous question. Here, I have modified the css to use the rgba() function add transparency so the conditional formatting can still be seen.
For the conditionally-formatted columns this works well.
But for the row numbers, and any columns that are not formatted, the transparent yellow colour indicating a row selection appears to overlap a blue colour.
I am not sure how to figure out where this blue colour comes from, and how to remove it. I can see that box-shadow is the property to set the colour of the selected row. I also tried adjusting the background-color
property, this doesn't work (doesn't go transparent). I am fairly new to css and I don't know how to find what other property might be causing this blue colour to appear.
I can work around this (by turning off row names and by setting all cells to a white background with formatStyle before applying the conditional formatting), but I wanted to ask this question here because: