How to Change Datatable Row Background Colour Based on the Condition in a Column, Rshiny

How to change Datatable row background colour based on the condition in a column, Rshiny

You can add a custom message which you can call using the session$onFlushed method. To keep the example succinct I have removed formatting and extra tabs. First the script and call to shiny. Notuce we equate to " Pass " rather then "Pass" etc. as xtable seems to add extra spacing:

library(shiny)
options(digits.secs=3)
script <- "
els = $('#logs tbody tr td:nth-child(2)');
console.log(els.length);
els.each(function() {
var cellValue = $(this).text();
if (cellValue == \" Pass \") {
$(this).parent().css('background-color', 'green');
}
else if (cellValue == \" Aggr \") {
$(this).parent().css('background-color', 'red');
}
else if (cellValue == \" Bad \") {
$(this).parent().css('background-color', 'grey');
}
});"
test_table <- cbind(rep(as.character(Sys.time()),2),rep('a',2),rep('b',2),rep('b',2),rep('c',2),rep('c',2),rep('d',2),rep('d',2),rep('e',2),rep('e',2))
colnames(test_table) <- c("Time","Test","T3","T4","T5","T6","T7","T8","T9","T10")

and the app

ui =navbarPage(inverse=TRUE,title = "Real-Time Logs",
tabPanel("Logs",icon = icon("bell"),
mainPanel(
htmlOutput("logs"))
, tags$script(sprintf('
Shiny.addCustomMessageHandler("myCallback",
function(message) {
%s
});
', script)
)
)
)
server <- (function(input, output, session) {
autoInvalidate1 <- reactiveTimer(3000,session)
my_test_table <- reactive({
autoInvalidate1()
other_data <- rbind(c(as.character(Sys.time()),(sample(c("Pass","Aggr","Bad"))[1]),round(c(rnorm(1),rnorm(1),rnorm(1),rnorm(1),rnorm(1),rnorm(1),rnorm(1),rnorm(1)),2)),
(c(as.character(Sys.time()),(sample(c("Pass","Aggr","Bad"))[1]),round(c(rnorm(1),rnorm(1),rnorm(1),rnorm(1),rnorm(1),rnorm(1),rnorm(1),rnorm(1)),2))))
test_table <<- rbind(apply(other_data, 2, rev),test_table)
session$onFlushed(function(){
session$sendCustomMessage(type = "myCallback", "some message")
})
as.data.frame(test_table)
})
output$logs <- renderTable({my_test_table()},include.rownames=FALSE)
})

runApp(list(ui = ui, server = server))

When you add back in the formatting and extra tabs it looks like:

Sample Image

DT in Shiny: Change only the colour of a single row

I can think of two possible workarounds:

  • Create a helper column that is 1 or 0, based on if your column is equal to myID or not, then use that column to style the table and hide that column.
  • Create a column mapping for all your unique values in the column ID, that defaults to a certain color, and set only the value corresponding to myID to orange.

A working example of the second option is given below. Hope this helps!


Sample Image

df = read.table(text='ID Value
102 306
41 800
101 783
105 193
myID 334',header=T)

library(DT)

my_vals = unique(df$ID)
my_colors = ifelse(my_vals=='myID','orange','grey')

datatable(df) %>%
formatStyle('ID', target = 'row',
backgroundColor = styleEqual(my_vals,my_colors))

Changing cell color of R shiny data table dependent on its value

If you use styleEqual function, it almost work except that it underlines also the reference row :

library(DT)
df <- head(iris)
ref <- df[1,]
color <- "orange"
datatable(df) %>%
formatStyle(1:5,
backgroundColor = styleEqual(ref[1:5], rep(color, 5)))

Changing color for cells on DT table in Shiny

Despite you haven't mentioned what the data looks like, I believe the solution is to change the following lines from

formatStyle(columns = "Rec_Color",
backgroundColor = styleEqual(
c("GREEN", "RED", "YELLOW"), c('green', "red", 'yellow'))

to

formatStyle(columns = "Sustainability Color",
backgroundColor = styleEqual(
c("GREEN", "RED", "YELLOW"), c('green', "red", 'yellow'))

The reason is that you have changed the column name by specifying the colnames= option.


There's another issue in your code, which is the formatStyle() function is called on DT::renderDataTable() but it should be DT::datatable(). So you should also modify the code to this:

    output$spTable <- DT::renderDataTable ({data <- TrustSp_Data  # Code for the trust species table and the selecInputs

if (input$Tax != "All") {
data <- data[data$Taxon == input$Tax,] # selectInput for Taxa
}

if (input$Rcolor != "All") {
data <- data[data$Rec_Color == input$Rcolor,] # selectInput for Recovery color
}

if (input$Cstat != "All") {
data <- data[data$Status == input$Cstat,] # selectInput for conservation status ( T&E, At-risk, etc...)
}

if (input$Rtime != "All") {
data <- data[data$Rec_Time == input$Rtime,] # selectInput for Recovery Timeline (1:6)
}

if (input$Autho != "All") {
data <- data[data$Authority == input$Autho,] # selectInput for federal Authority ( ESA, MBTA, etc...)
}
DT::datatable(
data, rownames=FALSE, #remove first column row numbers
extensions = c('ColReorder','Responsive',"FixedHeader"), # add "extensions = "Responsive" to add large number of columns

# caption = "Table 1: This is a sample caption for the table.", # Add caption at the top

caption = htmltools::tags$caption( # Add caption at the bottom of the table
style = 'caption-side: bottom; text-align: center;',
'Dataset:', htmltools::strong("Version 03-January 10, 2019")),

colnames = c("ID"=1,"Species Name"=3,"Scientific Name"=4, "Sustainability Color"=7, "Sustainability Timeline"=8, "ITIS ID"=9), # Change columns names
options = list(
fixedHeader = TRUE,
scrolly = TRUE,
colReorder = TRUE,
columnDefs = list(list(className = 'dt-center', targets = c(0,1,7))), # columns aligment to center
language = list(sSearch = "Search Table:"),
initComplete = JS(
"function(settings, json) {",
"$(this.api().table().header()).css({'background-color': '#22415e', 'color': '#fff'});",
"}")

)
) %>% formatStyle('Sustainability Color', backgroundColor = styleEqual(c("RED","GREEN","YELLOW"), c('red',"green","yellow")))

})


I hope this solves your problem.

BTW, when asking questions, the example is better to be reproducible. Your example is unreproducible because the data.frame is unknown and the code is only part of a large shiny app, which can't be run directly.

How to color the background of a cell in datatable (DT package) in R with column and row names or indices?

I'm not sure to get the question, but if you want to change the background color of a cell given by its row index and its column index (that's what I understand), you can do:

changeCellColor <- function(row, col){
c(
"function(row, data, num, index){",
sprintf(" if(index == %d){", row-1),
sprintf(" $('td:eq(' + %d + ')', row)", col),
" .css({'background-color': 'orange'});",
" }",
"}"
)
}
datatable(dat,
options = list(
dom = "t",
rowCallback = JS(changeCellColor(1, 2))
)
)

Color background of datatable cell based on shiny user input

I have created a small example, where the background color of selected cells changes based on user input. I hope this helps!

server.R

library(shiny)
library(DT)

shinyServer(function(input, output, session) {

dataReactive <- reactive({
return(mtcars[mtcars$gear==input$gear,])
})

output$table1 <- DT::renderDataTable({
df <- head(mtcars,100)

if(input$gear==1) color="red"
if(input$gear==2) color="blue"
if(input$gear==3) color="green"
if(input$gear==4) color="lightblue"

DT::datatable(df) %>% formatStyle(c("mpg", "cyl", "disp"),
backgroundColor = color)
})

})

ui.R

shinyUI(fluidPage(

sidebarLayout(
sidebarPanel(
selectInput("gear","Select gear:", choices = c(1,2,3,4))
),
mainPanel(
DT::dataTableOutput("table1")
)
)
))

Changing the color of the datatable rows based on multiple conditions

In this situation, I would store the color you want in each row of the table itself, and then use styleEqual to set the color of each row. (We'll also want to hide the column that contains the color.)

Add a column with the color you want to display for each row:

library(dplyr)
rawdata <- data.frame(
id = c(1,1,2,2,2,3,3),
time = c(45,92,30,100,79,199,248)
) %>%
mutate(row.color = case_when(id == 1 & time <= 30 ~ "#C6EFCE",
id == 1 & time <= 50 ~ "#FFEB9C",
id == 1 ~ "#FFC7CE",
id == 2 & time <= 45 ~ "#E60000",
id == 2 & time <= 90 ~ "#000000",
id == 2 ~ "#FFFFFF",
T ~ "#888888"))

(I used gray for id = 3 since the original post omits the actual colors for that condition.)

Use styleEqual to set cell colors in the time column and columnDefs to hide the column with color hex values:

library(DT)
datatable(
rawdata,
rownames = FALSE,
options=list(
pageLength = 20,
scrollX = TRUE,
dom = 'prlti',
initComplete =JS(
"function(settings, json) {",
"$(this.api().table().header()).css({'font-size': '20px', 'background-color': '#000', 'color': '#fff'});",
"}"),
columnDefs = list(list(className = 'dt-center', targets = "_all"),
list(targets = 2, visible = F)),
autowidth = T)
) %>%
formatStyle(
c("time"), "row.color",
backgroundColor = styleEqual(sort(unique(rawdata$row.color)), sort(unique(rawdata$row.color)))

) %>%
formatStyle(columns = c(1:NCOL(rawdata)),'font-size' = '25px',fontWeight = 'Bold')

We get the following result:

Sample Image

If you want to render white text in black rows, you can add yet another column with text.color and use styleEqual with the color option too.



Related Topics



Leave a reply



Submit