R DT datatable font size change - css

I want to change the font size of the entire data table., The default size is too large for what I want to display. I am trying to change the font-size of variable names and column content with formatStyle as follows
library(DT)
library(magrittr)
iris %>%
datatable() %>%
formatStyle(columns = colnames(.), `font-size` = '25%')
But, what is rendered is the same font size regardless of the changes. Tried different formats for font-size such as 'large, small' '150%, 50%' and '10px,20px,30px'

This question has already been addressed here.
To accomplish what you are trying to do:
library(DT)
library(magrittr)
iris %>%
datatable() %>%
DT::formatStyle(columns = colnames(iris), fontSize = '25%')

Was able to change the font-size for header and the columns by updating the CSS. The table header with JS api and the column content font size with the formatStyle as follows. However, the header and the footer font size stayed the same. I would like to change header/footer/body (entire font for the table) in one swoop. Is that possible?
datatable(head(iris, 20), options = list(
initComplete = JS(
"function(settings, json) {",
"$(this.api().table().header()).css({'font-size': '5px', 'background-color': '#c2d1f0', 'color': '#fff'});",
"}"))) %>% formatStyle(columns = colnames(.$x$data), `font-size` = '12px')
Attempted to update CSS for columns with the following command without success
"$(this.api().columns().data()).css({'font-size': '5px'});"
"$(this.api().table().footer()).css({'font-size': '10px});"
"$(this.api().tables().body()).css({'font-size': '10px'});"

datatable(head(iris, 20), options = list(
initComplete = JS("
function(settings, json) {
$(this.api().table().header()).css({
'font-size': '12px',
});
}
")
)) %>%
formatStyle(columns = colnames(.$x$data), `font-size` = "12px")

Related

Freeze panes for a very wide table in gt

I am trying to get a gt table to freeze it's panes (ideally both for the columns and rows). I found this awesome gist here which gets me part of the way there: https://gist.github.com/jthomasmock/e3c7873fc505b8e9461b823b0a6954cc
However when I create a very wide table that pushes beyond the page, I end up with two scroll bars: one for the header and one for the body. Is there any way so that those two divs can share a scroll bar? I have included a reprex which illustrates the issue.
library(htmltools)
library(gt)
gt_scroll <- function(data, gt_fun){
# empty table
head_data <- data[0,]
tab_topp <- head_data %>%
gt_fun()
tab_body <- data %>%
gt_fun() %>%
tab_options(
column_labels.hidden = TRUE,
container.height = gt::px(750)
)
htmltools::div(
htmltools::tags$div(
tab_topp %>% as_raw_html(),
style = htmltools::css(
`padding-right` = "12px"
)
),
htmltools::tags$div(
tab_body,
style = htmltools::css(
`overflow-x` = "hidden",
`overflow-y` = "auto",
height = "500px"
)
)
) %>%
html_print()
}
gt_scroll(
head(starwars),
function(x){
gt(x) %>%
cols_width(everything()~ px(50)) %>%
tab_options(container.width = px(400))
}
)

Shiny DataTable - How to change filter size?

I've this Shiny app:
The filter size is too narrow so I can't see the whole words.
I want to make the filter box wider without changing the table/column size, just the filter box.
this is my code:
library(DT)
iris2 = iris[c(1:10, 51:60, 101:110), ]
# no clear buttons
datatable(iris2, options = list(autoWidth = TRUE), filter = list(
position = 'top', clear = FALSE
))
Is it possible?

Flexdashboard checkbox flows off page

I created a datatable in a flexdashboard with a checkbox, but the checkbox flows off the page. I tried to adjust the padding {data-padding = 10} but nothing changed. Below is the code and a picture of what the dashboard looks like. How do I move everything to the right so that it's aligned with the title of the page?
---
title: "School Dashboard"
author: "Shannon Coulter"
output:
flexdashboard::flex_dashboard:
orientation: rows
social: menu
source_code: embed
theme: spacelab
---
```{r}
library(tidyverse)
library(crosstalk)
library(DT)
library(flexdashboard)
```
Student Lookup
================================================================================
### Chronic Absenteeism Lookup
```{r ca-lookup, echo=FALSE, message=FALSE, warning=FALSE}
ican_tab <- tibble(
year = c("2022", "2022", "2022", "2022", "2022"),
date = c("March", "March","March","March","March"),
school = c("ABC", "CDE","ABC","DEF","GHI"),
grade = c("6th", "7th","8th","4th","5th"),
race_eth = c("White", "Hispanic","White","Filipino","White"),
abs_levels = c("Not At-Risk of Chronic Absenteeism", "At-Risk of Chronic Absenteeism",
"Severe Chronic Absenteeism", "Severe Chronic Absenteeism",
"Moderate Chronic Absenteeism")
)
sd <- SharedData$new(ican_tab)
bscols(list(
filter_checkbox("abs_levels", "Level", sd, ~ abs_levels, inline = TRUE),
datatable(
sd,
extensions = c("Buttons",
"Scroller"),
options = list(
autoWidth = TRUE,
scrollY = F,
columnDefs = list(list(
className = 'dt-center',
targets = c(2, 3, 4, 5)
)),
lengthMenu = c(5, 10, 25, 100),
dom = "Blrtip",
deferRender = TRUE,
scrollY = 300,
scroller = TRUE,
buttons = list('copy',
'csv',
'pdf',
'print')
),
filter = "top",
style = "bootstrap",
class = "compact",
width = "100%",
colnames = c(
"Year",
"Date",
"School",
"Grade",
"Race",
"Level"
)
) %>%
formatStyle('abs_levels',
backgroundColor = styleEqual(
unique(ican_tab$abs_levels),
c(
"#73D055ff",
"#95D840FF",
"#B8DE29FF",
"#DCE319FF"
)
))
))
```
[![enter image description here][1]][1]
The easiest way to address this is probably to add style tags to your dashboard. You can put this anywhere. I usually put it right after the YAML or right after my first R chunk, where I just place my knitr options and libraries. This does not go inside an R chunk.
<style>
body { /*push content away from far right and left edges*/
margin-right: 2%;
margin-left: 2%;
}
</style>
Update based on your updated question and comments
I don't have the content around your table, so I will give you a few options that work. For the most part, any one option won't be enough. You can mix and match the options that work best for you.
This is what I've got for the original table:
Option 1: you can use CSS to push the table away from the edges (as in my original response
Option 2: change the font sizes
Option 3: constrain the size of the datatable htmlwidget
Option 4: manually make the columns narrower
Option 5: alter the filter labels (while keeping the same filters and data)
Aesthetically looks the best? It depends on what else is on the dashboard.
I think you will need the original CSS (option 1, in my original answer) regardless of what other options you choose to use.
Option 1 is above
Option 2
To change the font sizes, you have to modify the filter_checkbox and the datatable after they're made. Instead of presenting all of the programming code, I'm going to show you want to add or modify and how I broke down the objects.
Your original code for filter_checkbox remains the same. However, you'll assign it to an object, instead of including it in bscols.
Most of the code in your datatable will remain the same. there is an addition to the parameter options. I've included the original and change for that parameter.
# filter checkbox object
fc = filter_checkbox(...parameters unchanged...)
fc$attribs$style <- css(font.size = "90%") # <-change the font size
dt = datatable(
...
...
options = list( # this will be modified
autoWidth = TRUE, # <- same
scrollY = F, # <- same
initComplete = JS( # <- I'M NEW! change size of all font
"function(settings, json) {",
"$(this.api().table().container()).css({'font-size': '90%'});",
"}"),
columnDefs = list( # <- same
list(className = 'dt-center', targets = c(2, 3, 4, 5))),
...
... # remainder of datatable and formatStyles() original code
)
# now call them together
bscols(list(fc, dt))
The top version is with 90% font size, whereas the bottom is the original table.
Option 3
To constrain the size of the datatable widget, you'll need to create the object outside of bscols, like I did in option 2. If you were to name your widget dt as in my example, this is how you could constrain the widget size. This example sets the datatable to be 50% of the width and height viewer screen (or 1/4 of the webpage). Keep in mind that the filters are not part of the widget, so in all, the table is still more than 1/4th of the webpage. You will have to adjust the size for your purposes, of course. I recommend using a dynamic sizing mechanism like vw, em, rem, and the like.
dt$sizingPolicy$defaultWidth <- "50vw"
dt$sizingPolicy$defaultHeight <- "40vh"
The top image has options 1, 2, and 3; the bottom is the original table.
Option 4
To modify the width of the columns, you can add this modification to the parameter options in you call to datatable. This could be good, because most of the columns don't require as much width as the last column. However, if you change the font size or scale the table, it will change the font size dynamically, so this option may not be necessary.
Despite using em here, in the course of this going from R code to an html_document, it was changed to pixels. So this is not dynamically sized. (Not a great idea! Sigh!)
columnDefs = list(
list(className = 'dt-center', targets = c(2, 3, 4, 5)),
list(width = '5em', targets = c(1,2,3,4,5))), # <- I'm NEW!
Option 5
For this option, I took the programming behind crosstalk::filter_checkbox() and modified the code a bit. I changed the function to filter_checkbox2(). If you use it, you can render it both ways and just keep the one you like better.
This first bit of code is the three functions that work together to create a filter_checkbox object with my modifications so that you can have a label that isn't exactly the same as the levels.
It's important to note that the filters are alphabetized by datatable. It doesn't matter if they're factors, ordered, etc. If you use this new parameter groupLabels, they need to be in an order that aligns with the levels when they're alphabetized.
I put this code in an include=F chunk by itself:
# this is nearly identical to the original function
filter_checkbox2 = function (id, label, sharedData, group,
groupLabels = NULL, # they're optional
allLevels = FALSE, inline = FALSE, columns = 1) {
options <- makeGroupOptions(sharedData, group,
groupLabels, allLevels) # added groupLabels
labels <- options$items$label
values <- options$items$value
options$items <- NULL
makeCheckbox <- if (inline)
inlineCheckbox
else blockCheckbox
htmltools::browsable(attachDependencies(tags$div(id = id,
class = "form-group crosstalk-input-checkboxgroup crosstalk-input",
tags$label(class = "control-label", `for` = id, label),
tags$div(class = "crosstalk-options-group",
crosstalk:::columnize(columns,
mapply(labels, values, FUN = function(label, value) {
makeCheckbox(id, value, label)
}, SIMPLIFY = FALSE, USE.NAMES = FALSE))),
tags$script(type = "application/json", `data-for` = id,
jsonlite::toJSON(options, dataframe = "columns",
pretty = TRUE))),
c(list(crosstalk:::jqueryLib()),crosstalk:::crosstalkLibs())))
}
inlineCheckbox = function (id, value, label) { # unchanged
tags$label(class = "checkbox-inline",
tags$input(type = "checkbox",
name = id, value = value),
tags$span(label))
}
# added groupLabels (optional)
makeGroupOptions = function (sharedData, group, groupLabels = NULL, allLevels) {
df <- sharedData$data(withSelection = FALSE, withFilter = FALSE,
withKey = TRUE)
if (inherits(group, "formula"))
group <- lazyeval::f_eval(group, df)
if (length(group) < 1) {
stop("Can't form options with zero-length group vector")
}
lvls <- if (is.factor(group)) {
if (allLevels) {levels(group) }
else { levels(droplevels(group)) }
}
else { sort(unique(group)) }
matches <- match(group, lvls)
vals <- lapply(1:length(lvls), function(i) {
df$key_[which(matches == i)]
})
lvls_str <- as.character(lvls)
if(is.null(groupLabels)){groupLabels = lvls_str} # if none provided
if(length(groupLabels) != length(lvls_str)){ # if the # labels != the # groups
message("Warning: The number of group labels does not match the number of groups.\nGroups were used as labels.")
groupLabels = lvls_str
}
options <- list(items = data.frame(value = lvls_str, label = groupLabels, # changed from lvls_str
stringsAsFactors = FALSE), map = setNames(vals, lvls_str),
group = sharedData$groupName())
options
}
When I used this new version of I changed label = "Level" to label = "Chronic Absenteeism Level". Then removed " Chronic Absenteeism" from the filter labels. The data and the datatable does not change, just the filter checkbox labels.
filter_checkbox2("abs_levels", "Chronic Absenteeism Level",
sd, ~ abs_levels, inline = TRUE,
groupLabels = unlist(unique(ican_tab$abs_levels)) %>%
str_replace(" Chronic Absenteeism", "") %>% sort())
The first image is your table with options 1, 2, 3, and 5 (not 4).
The top version in the next image has options 1, 2, 3, and 5 (not 4). The bottom is the original table. After that
If I've left anything unclear or if have any other questions, let me know.

Highlight part of a string in a cell content based on a list of predefined words

Hi am trying to highlight list of words in a DT table, its coloring the cell but not the text as per the below code. Is there any way I can color only the word inside text?
Eg: if the data frame has 3 columns in which the text column contains (Financial duty of the product has increase trifold in last 3 years) I want to color only trifold and make it bold.
DT::datatable(data, filter=list(position = 'top', clear = TRUE), rownames = F,class = 'cell-border stripe compact',
options = list(
columnDefs = list(list(className = 'dt-center', targets =c(1,4))),lengthMenu = c(50,100))) %>% formatDate('date', 'toDateString') %>% formatRound('score',3) %>% formatStyle('text', target = 'row',backgroundColor=styleContain("trifold","yellow"))
formatStyle won't get you the result you seek, as it'll change the CSS properties of the whole element and there is no way to actually stylize some parts of the text. What i'd suggest is to actually change the content of each cell that contains trifold and wrap it in some html element, <mark> tag seems to be the best fit as by default it will change the background-color to yellow you can change the following code to use a span if you want:
# wraps word in the specified tag
wrap_in <- function(.df, column, word, tag){
class<-""
if(grepl("\\.", tag)) {
class <- sub(".+?\\.(.+)", " class='\\1'", tag)
tag <- sub("\\..+", "", tag)
}
.df[[column]] <- gsub(sprintf("\\b(%s)\\b", paste0(word,collapse="|")), sprintf("<%1$s%2$s>\\1</%1$s>", tag, class), .df[[column]])
.df
}
# create the data.table
mts %>% wrap_in( "text", "trifold", "mark") %>%
datatable( escape=F, filter=list(position = 'top', clear = TRUE), rownames = F,class = 'cell-border stripe compact',
options = list(columnDefs = list(list(className = 'dt-center', targets =c(1,4))),lengthMenu = c(50,100))) %>% formatRound('carb',3) -> dt
# prepend css to embolden text found in <mark>
dt %>%
htmlwidgets::prependContent(htmltools::tags$style("mark {font-weight: 700;}"))
Using a span
mts %>% wrap_in( "text", "trifold", "span.highlight") %>%
datatable( escape=F, filter=list(position = 'top', clear = TRUE), rownames = F,class = 'cell-border stripe compact',
options = list(columnDefs = list(list(className = 'dt-center', targets =c(1,4))),lengthMenu = c(50,100))) %>% formatRound('carb',3) %>%
htmlwidgets::prependContent(htmltools::tags$style("span.highlight {color:yellow;font-weight: 700;}"))
DATA
mtcars %>% mutate(text=case_when(cyl==6 ~ "Financial duty of the product has increase trifold in last 3 years", T ~ "Financial duty of the product had no significant increase")) -> mts

DT::datatable – Format selected column?

Can you please help me with DT::datatable column formatting? I have for example this table:
DT::datatable(iris,
class = 'row-border stripe hover compact',
rownames = F,
autoHideNavigation = T,
options = list(pageLength = nrow(summary.month),
searching = F,
paging = F,
info = F))
I need to set:
1st column: bold, aligned left
3rd coumn: bold, aligned right
I found, that I should use columns.ClassName, but how to set the class styles in R?
The html output of datatable will be used in R markdown document then.
It has been a while since this question was initially asked, but I just had this same problem. Here is a simpler solution that doesn't require editing the source data or calling JS, but instead uses functions within the DT package itself.
DT::datatable(iris,
class = 'row-border stripe hover compact',
rownames = F,
autoHideNavigation = T, escape =FALSE) %>%
formatStyle(columns = c("Sepal.Length"), fontWeight = 'bold', `text-align` = 'left') %>%
formatStyle(columns = c("Petal.Length"), fontWeight = 'bold', `text-align` = 'right')
So far the only way I can get it to work is by manually setting the HTML tags first, and then using escape = FALSE
Here we wrap Sepal.Length in the bold HTML tag:
iris$SepalLength2 <- paste0("<b>", iris$Sepal.Length, "</b>")>
Then use escape = FALSE so that the HTML tags are parsed.
datatable(iris,
class = 'row-border stripe hover compact',
rownames = F,
autoHideNavigation = T, escape =FALSE)
Edit:
For align left/right, you can wrap in a <p align ="left"></p>
So: iris$SepalLength2 <- paste0('<p align ="right"><b>', iris$Sepal.Length, '</b></p>')
Note that I am neither an HTML guru, nor an expert on this particular library, but this seems like one way to get your desired result.
You don't need to modify the contents of your data. Instead, you can use the rowCallback option:
library(DT)
rowCallback <- c(
"function(row, data, index){",
" $(this.api().cell(index, 0).node())",
" .css('text-align', 'left')",
" .css('font-weight', 'bold');",
" $(this.api().cell(index, 2).node())",
" .css('text-align', 'right')",
" .css('font-weight', 'bold');",
"}"
)
DT::datatable(iris,
class = 'row-border stripe hover compact',
rownames = FALSE,
autoHideNavigation = TRUE,
options = list(pageLength = 5,
searching = FALSE,
paging = TRUE,
info = FALSE,
rowCallback = JS(rowCallback))
)

Resources