Highlighting table Cells based on headers mentioned in one column data - r

I am working on below code definition:
If first column value is 'Modified' and second column contains column names which's values has been changed
based on this the data cell needs to be highlighted
I am referring to the code as reference : formatStyle over multiple columns DT R
Below is the definition of table
*
input_data1 <- data.frame(Record_Status = c("Modified","Modified","Modified","Modified","Modified","Modified","Modified","Modified","Modified"),
Field_Changed = c("Brand,ratio","cost","Name","ratio,Name","cost","Brand,cost","ratio,cost","cost","Name"),
Brand = c(3,6,9,12,15,18,21,24,27),
ratio = c (1,2,3,4,5,6,7,8,9),
cost = c(3,6,9,12,15,18,21,24,27),
Name = c("A","B","C","A","B","C","A","B","C"),
stringsAsFactors = FALSE)
hepl_1=tapply(1:ncol( input_data1),function(i) ifelse(( input_data1[[1]]=="Modified" &
str_detect( input_data1[[2]], names( input_data1)[i])),
"red","white"))
help_3=as.matrix( input_data1[1:ncol( input_data1)])
My datatable definition is as below:
output$mod_table <- DT::renderDataTable({
DT::datatable(input_data,selection = 'single',
escape=F, plugins = "ellipsis",
class = 'white-space: nowrap',
filter = list(position = 'top', clear = FALSE) , editable = TRUE,
extensions = c('Buttons','AutoFill','FixedHeader', 'KeyTable','ColReorder'),
rownames = F,
options = list(
keys = TRUE, colReorder = list(realtime = FALSE),
fixedHeader = TRUE, autoFill = list(focus = 'click', horizontal = FALSE) ,
autoWidth=TRUE, pageLength = 7 ,list(target = 'cell'),
lengthMenu = list(c(2, 50, -1), c('2', '50', 'All')), dom = 'lBfrtip',buttons = list(
c('colvis','pdf','excel'),
list(
extend = "collection",
text = 'Show All',
action = DT::JS("function ( e, dt, node, config ) { dt.page.len(-1);
dt.ajax.reload();
}"))))) %>% formatStyle(names(input_data), backgroundColor = styleEqual(help_3, hepl_1))
})
click here for image definition of Hepl1
click here for o/p datatable image - which is not giving me correct highlights
### Libraries
library(shiny)
library(dplyr)
library(DT)
### Data
input_data <- data.frame(Record_Status = c("Modified","Modified","Modified","Modified","Modified","Modified","Modified","Modified","Modified"),
Field_Changed = c("Brand,ratio","cost","Name","ratio,Name","cost","Brand,cost","ratio,cost","cost","Name"),
Brand = c(3,6,9,12,15,18,21,24,27),
ratio = c (1,2,3,4,5,6,7,8,9),
cost = c(3,6,9,12,15,18,21,24,27),
Name = c("A","B","C","A","B","C","A","B","C"),
stringsAsFactors = FALSE)
### Module
modFunction <- function(input, output, session, data,reset) {
v <- reactiveValues(data = data)
proxy = dataTableProxy("mod_table")
### Reset Table
observeEvent(reset(), {
v$data <- data # your default data
})
hepl_1=sapply(1:ncol(input_data),function(i) ifelse(input_data[[1]]=="Modified" &
str_detect(input_data[[2]], names(input_data)[i]),
"yellow","white"))
help_3=as.matrix(input_data)
#print(isolate(colnames(v$data)))
output$mod_table <- DT::renderDataTable({
DT::datatable(input_data,selection = 'single',
escape=F, plugins = "ellipsis",
class = 'white-space: nowrap',
filter = list(position = 'top', clear = FALSE) , editable = TRUE,
extensions = c('Buttons','AutoFill','FixedHeader', 'KeyTable','ColReorder'),
rownames = F,
options = list(
keys = TRUE, colReorder = list(realtime = FALSE),
fixedHeader = TRUE, autoFill = list(focus = 'click', horizontal = FALSE) ,
autoWidth=TRUE, pageLength = 7 ,list(target = 'cell'),
lengthMenu = list(c(2, 50, -1), c('2', '50', 'All')), dom = 'lBfrtip',buttons = list(
c('colvis','pdf','excel'),
list(
extend = "collection",
text = 'Show All',
action = DT::JS("function ( e, dt, node, config ) { dt.page.len(-1);
dt.ajax.reload();
}"))))) %>% formatStyle(names(input_data), backgroundColor = styleEqual(help_3, hepl_1))
})
}
modFunctionUI <- function(id) {
ns <- NS(id)
DT::dataTableOutput(ns("mod_table"))
}
### Shiny App
shinyApp(
ui = basicPage(
mainPanel(
actionButton("reset", "Reset"),
tags$hr(),
modFunctionUI("editable")
)
),
server = function(input, output) {
demodata<-input_data
callModule(modFunction,"editable", demodata,
reset = reactive(input$reset))
}
)

Related

How to download only the selected columns in a dataframe using Colvis from DT in Shiny?

I am using the button colvis from the DT package to select which columns I would like to show in the table. Here you have more info about the button colvis.
It works perfectly fine, it hides the columns that I don't want to select and the result is shown to the user.
However, it seems that this info is not updated when I download the file.
If I only select "Petal.Width" and "Species":
Then, I download the file... and I open it. I still have all the columns and not the selected ones.
I have been trying to find a solution, but I haven't found anything.
Does anyone know how to fix it?
Thanks in advance.
Here is my code:
library(shiny)
library(DT)
ui <- fluidPage(
dataTableOutput("table")
)
server <- function(input, output, session) {
output$table <- renderDataTable({
datatable(
iris,
filter = list(position = 'top', clear = FALSE),
selection = "none", #this is to avoid select rows if you click on the rows
rownames = FALSE,
extensions = 'Buttons',
options = list(
scrollX = TRUE,
dom = 'Blrtip',
buttons =
list(I('colvis'),'copy', 'print', list(
extend = 'collection',
buttons = list(
list(extend = 'csv', filename = paste0("iris"), title = NULL),
list(extend = 'excel', filename = paste0("iris"), title = NULL)),
text = 'Download'
)),
lengthMenu = list(c(10, 30, 50, -1),
c('10', '30', '50', 'All'))
),
class = "display"
)
})
}
shinyApp(ui, server)
library(DT)
datatable(
iris,
extensions = "Buttons",
options = list(
dom = "Bfrtip",
buttons = list(
I("colvis"),
list(
extend = "collection",
text = "Download",
buttons = list(
list(
extend = "csv",
exportOptions = list(
columns = ":visible"
)
)
)
)
)
)
)
Thanks to Stéphane Laurent's answer, I managed to find an answer.
I had some problems to have both buttons (csv and excel) and how to organise the lists with the proposed solution, but I found the way to do it.
I will add the answer with the original code just in case someone has problems like me.
library(shiny)
library(DT)
ui <- fluidPage(
dataTableOutput("table")
)
server <- function(input, output, session) {
output$table <- renderDataTable({
datatable(
iris,
filter = list(position = 'top', clear = FALSE),
selection = "none", #this is to avoid select rows if you click on the rows
rownames = FALSE,
extensions = 'Buttons',
options = list(
scrollX = TRUE,
dom = 'Blrtip',
buttons =
list(I('colvis'),'copy', 'print', list(
extend = 'collection',
text = 'Download',
buttons = list(
list(
extend = "csv", filename = paste0("iris"), title=NULL,
exportOptions = list(
columns = ":visible")
),
list(
extend = "excel", filename = paste0("iris"), title=NULL,
exportOptions = list(
columns = ":visible")
)
)
)),
lengthMenu = list(c(10, 30, 50, -1),
c('10', '30', '50', 'All'))
),
class = "display"
)
})
}
shinyApp(ui, server)

Add background color to DT rows in shiny

I have some code that creates a DT table with radio buttons. On top of that I need to add particular colors to each row. I have been trying to use formatStyle too add a different color to each row but I haven't gotten the syntax correct.
Here is the working code:
library(shiny)
library(DT)
c1 = "This is comment 1"
c2 = "This is comment 2"
c3 = "This is comment 3"
c4 = "This is comment 4"
c5 = "This is comment 5"
comments1 = list(c1,c2,c3,c4,c5)
m1 = matrix(
as.character(1:5), nrow = 5, ncol = 1, byrow = FALSE,
dimnames = list(comments1, LETTERS[1])
)
for (i in seq_len(ncol(m1))) {
m1[, i] = sprintf(
'<input type="radio" name="%s" value="%s"/>',
'AValue', m1[,i]
)
}
callback1 <- c(
"var LETTERS = ['AValue'];",
"for(var i=0; i < LETTERS.length; ++i){",
" var L = LETTERS[i];",
" $('input[name=' + L + ']').on('click', function(){",
" var name = $(this).attr('name');",
" var value = $('input[name=' + name + ']:checked').val();",
" Shiny.setInputValue(name, value);",
" });",
"}"
)
ui <- fluidPage(
title = 'Radio buttons in a table',
DT::dataTableOutput('foo1'),
verbatimTextOutput('sel1'),
)
server <- function(input, output, session) {
output$foo1 = DT::renderDataTable(
m1, escape = FALSE, selection = 'none', server = FALSE,
options = list(dom = 't', paging = FALSE, ordering = FALSE),
callback = JS(callback1),
)
output$sel1 = renderPrint({
input[["AValue"]]
})
}
shinyApp(ui, server)
Here are the some of the different variations of the calls that I have tried.
#formatStyle needs to be called on DT:datatable()
#Test adding formatStyle
output$foo1 <- DT::renderDataTable({
dat <- datatable(m1, escape = FALSE, selection = 'none',
options = list(dom = 't', paging = FALSE, ordering = FALSE))
callback = JS(callback1) %>% formatStyle(0, target='row', backgroundColor = styleEqual(3,'red'))
})
or
#Test adding formatStyle
output$foo1 <- DT::renderDataTable({
DT::datatable(m1,escape = FALSE, selection = 'none',
options = list(dom = 't', paging = FALSE, ordering = FALSE, callback = JS(callback1))
%>% formatStyle(0, target='row', backgroundColor = styleEqual(3,'red')))
})
Any help would be greatly appreciated.
Thanks!
You need to pass the table as an argument of the formatStyle. To do that inside the renderDataTable you can use the datatable function.
It seems that your condition to assign a color to a row is not going to match any row. You need to put something that could be in the column. Below is an example where an entire row has a red background when the content in column 0 is equal to "This is comment 3".
output$foo1 = DT::renderDataTable({
DT::datatable(
m1, escape = FALSE, selection = 'none',
options = list(dom = 't', paging = FALSE, ordering = FALSE),
callback = JS(callback1)
) %>% formatStyle(0, target='row', backgroundColor = styleEqual('This is comment 3','red'))
}, server = FALSE
)
Perhaps you can define a new column with row_numbers and assign colors to the rows of interest. You can make the row_num column not visible. Try this
mycolors <- c('green','pink','red','yellow','orange')
output$foo1 = DT::renderDataTable({
m2 <- as.data.frame(m1) %>% dplyr::mutate(row_num = 1:n())
datatable( m2, escape = FALSE,
selection = 'none',
extensions = c("Select", "Buttons"),
callback = JS(callback1), ### needs double-click to select the radiobutton
options = list(dom = 't', paging = FALSE, ordering = FALSE,
columnDefs = list(list(visible=FALSE, targets=2))
)
) %>% formatStyle(2,
target='row',
backgroundColor = styleEqual(c(1:5),mycolors))
}, server = FALSE,
#callback = JS(callback1) ### does not recognize input[["AValue"]]
)

R shiny and DT not rendering with column width set of specific column with some DT options

I have this piece of code. The DT datatable does not render at all. It shows the columns, and nothing else. I posted a related question earlier, but apparently, this issue needed to be posted as a separate question. I am.
Any idea of what I am missing?
library(dplyr)
library(shiny)
library(DT)
library(data.table)
mtcars <- mtcars[1:5, ]
ui <- fluidPage(
fluidRow(
dataTableOutput(('mtcarsDT')),
)
)
server <- function(input, output, session) {
output$mtcarsDT <- DT::renderDataTable({
recFeedbackCol <- lapply(1:nrow(mtcars), function(recnum)
as.character(
radioButtons(
paste0(
'rec', recnum),
'',
choices = c('good' = 'Good', 'bad' = 'Bad', 'neutral' = 'Neutral'),
inline = TRUE
)
)
)
recFeedbackCol <- tibble(feedback = recFeedbackCol)
mtcars <- bind_cols(
mtcars,
recFeedbackCol
)
mtcars %>%
DT::datatable(
extensions = 'FixedColumns',
rownames = FALSE,
escape = FALSE,
class="compact cell-border",
options = list(
pageLength = 15,
lengthChange = FALSE,
scrollX = TRUE,
searching = FALSE,
dom = 't',
ordering = TRUE,
fixedColumns = list(leftColumns = 2),
preDrawCallback = JS(
'function() { Shiny.unbindAll(this.api().table().node()); }'
),
drawCallback = JS(
'function() { Shiny.bindAll(this.api().table().node()); } '
),
autoWidth = TRUE,
columnDefs = list(
list(width = '200px', targets = ncol(mtcars))
)
)
)
})
}
shinyApp(ui = ui, server = server)
The problem seems to be targets parameter of columnDefs. It accepts column index starting from 0. To specify the last column, it needs to be reduced by 1.
columnDefs = list(
list(width = '200px', targets = ncol(mtcars) - 1)
)

Replace options in R Shiny datatable on the fly

I would like to change the language of a datatable on the fly
I have the following code
output$prr2 <- renderDataTable({
prr()}, options = list(
autoWidth = TRUE,
columnDefs = list(list(width = '50', targets = c(1, 2) ) ),
language = list(url = if(getLanguage()=='gr') '//cdn.datatables.net/plug-ins/1.10.11/i18n/Greek.json' else
'//cdn.datatables.net/plug-ins/1.10.11/i18n/English.json' ))
getLanguage() returns the value of selected_language, prr() returns a data.frame.
I want to do something like this in order to change options of the table after selecting a different language in a dropdown selected_language
proxy = dataTableProxy('prr2')
observeEvent(input$selected_language,{ replace language option of datatable prr2})
Any idea about this?
I can't test since you don't provide a reproducible example. I would try
output$prr2 <- renderDataTable({
prr()
}, options = exprToFunction(list(
autoWidth = TRUE,
columnDefs = list(list(width = '50', targets = c(1, 2))),
language = list(
url = ifelse(getLanguage()=='gr',
'//cdn.datatables.net/plug-ins/1.10.11/i18n/Greek.json',
'//cdn.datatables.net/plug-ins/1.10.11/i18n/English.json')
)
)))
EDIT
output$prr2 <- renderDataTable({
datatable(
prr(),
options = exprToFunction(list(
autoWidth = TRUE,
columnDefs = list(list(width = '50', targets = c(1, 2))),
language = list(
url = ifelse(getLanguage()=='gr',
'//cdn.datatables.net/plug-ins/1.10.11/i18n/Greek.json',
'//cdn.datatables.net/plug-ins/1.10.11/i18n/English.json')
)
)
)
)
})
EDIT 2
Full app which works:
library(shiny)
library(DT)
ui <- fluidPage(
radioButtons("language", "Language", choices = c("gr", "en")),
DTOutput("prr2")
)
server <- function(input, output, session){
output$prr2 <- renderDT({
datatable(
iris,
options = exprToFunction(list(
autoWidth = TRUE,
columnDefs = list(list(width = '50', targets = c(1, 2))),
language = list(
url = ifelse(input$language=='gr',
'//cdn.datatables.net/plug-ins/1.10.11/i18n/Greek.json',
'//cdn.datatables.net/plug-ins/1.10.11/i18n/English.json')
)
))
)
})
}
shinyApp(ui, server)

How to resize a datatable in order to fit it in a box() for shinyDashboard

I don't know how to make sure the size of my DT::renderDataTable fit in my box.
Here is a picture of my Shiny Render
Does anybody know how to make sure the table fit in the box ? Or can I add a slider under the table to scroll around other variables that are not on the screen ?
Here is my code:
server.R
output$table = DT::renderDataTable({
DT::datatable(
round(df,2),
rownames = TRUE,
extensions = 'Buttons',
options = list(
autoWidth = FALSE,
columnDefs = list(list(width = "125px", targets = "_all")),
dom = 'tpB',
lengthMenu = list(c(5, 15, -1), c('5', '15', 'All')),
pageLength = 15,
buttons = list(
list(
extend = "collection",
text = 'Show More',
action = DT::JS("function ( e, dt, node, config ) {
dt.page.len(50);
dt.ajax.reload();}")
),list(
extend = "collection",
text = 'Show Less',
action = DT::JS("function ( e, dt, node, config ) {
dt.page.len(10);
dt.ajax.reload();}")
)
)
)
)
})
body.R
box( title = "A little taste of the dataset",
width = 12,
DT::dataTableOutput("table") )
You can simply add scrollX = TRUE to the datatable options:
library(shiny)
library(shinydashboard)
DF <- data.frame(replicate(50, runif(1000, 0, 10)))
ui <- fluidPage(box(
title = "A little taste of the dataset",
width = 12,
DT::dataTableOutput("myTable")
))
server <- function(input, output, session) {
output$myTable = DT::renderDataTable({
DT::datatable(
round(DF, 2),
rownames = TRUE,
extensions = 'Buttons',
options = list(
autoWidth = FALSE, scrollX = TRUE,
columnDefs = list(list(
width = "125px", targets = "_all"
)),
dom = 'tpB',
lengthMenu = list(c(5, 15,-1), c('5', '15', 'All')),
pageLength = 15,
buttons = list(
list(
extend = "collection",
text = 'Show More',
action = DT::JS(
"function ( e, dt, node, config ) {
dt.page.len(50);
dt.ajax.reload();}"
)
),
list(
extend = "collection",
text = 'Show Less',
action = DT::JS(
"function ( e, dt, node, config ) {
dt.page.len(10);
dt.ajax.reload();}"
)
)
)
)
)
})
}
shinyApp(ui = ui, server = server)

Resources