DT::formatStyle 设置基于字符向量的数据表行的背景颜色 HTML

DT::formatStyle to set background colour of datatable row based on character vector with raw HTML

我正在尝试根据具有原始 HTML 的向量设置数据 table 行的背景颜色(我这样做 而不是 转义以便呈现上标)。此时我可以做一个或另一个:通过转义 HTML 正确设置背景颜色,或者通过不转义 HTML 正确设置上标,但不能同时进行。

我们可以使用 DT::formatStyleDT::styleEqual 来根据我们 table 中的变量设置数据特定行的背景颜色 table;例如,当 V1 == 'Crackers':

时将背景设置为灰色
library(DT)

df <- data.frame(
    V1 = c('Cheese<sup>1</sup>', 'Crackers', 'Taters'),
    v2 = c(10, 4, 7))

datatable(df, escape = FALSE) %>%
    formatStyle('V1',
        target = 'row',
        backgroundColor = styleEqual(
            levels = 'Crackers',
            values = 'gray'))

我想做的是设置特定行的背景颜色,其 V1 值包含非转义的 HTML 上标(即 Cheese<sup>1</sup>)。请注意,我们设置 escape = FALSE 以正确呈现上标。将 styleEquallevels 参数设置为包含 HTML 的字段不起作用:

datatable(df, escape = FALSE) %>%
    formatStyle('V1',
        target = 'row',
        backgroundColor = styleEqual(
            levels = c('Cheese<sup>1</sup>', 'Crackers'),
            values = c('gray', 'gray')))

问题可能是 styleEquallevels 参数上调用了 htmltools::htmlEscape,即

htmltools::htmlEscape('Cheese<sup>1</sup>')
[1] "Cheese&lt;sup&gt;1&lt;/sup&gt;"

这显然不会直接匹配 Cheese<sup>1</sup>

如果我们恢复到默认 escape 设置,即 datatable(df, escape = TRUE) %>% ...,那么我们会得到正确的背景颜色,但是当然,上标不起作用。

我找到了一个变通方法,它涉及修改 styleEqual 函数,添加一个额外的参数 escape,允许我们跳过对 htmlEscape 的调用。例如,

styleEqual2 <- function (levels, values, default = NULL, escape = TRUE) 
{
    n = length(levels)
    if (n != length(values)) 
        stop("length(levels) must be equal to length(values)")
    if (!is.null(default) && (!is.character(default) || length(default) != 
                              1)) 
        stop("default must be null or a string")
    if (n == 0) 
        return("''")
    if ((is.character(levels) || is.factor(levels)) && escape)
        levels = htmltools::htmlEscape(levels)
    levels = DT:::jsValues(levels)
    values = DT:::jsValues(values)
    js = ""
    for (i in seq_len(n)) {
        js = paste0(js, sprintf("value == %s ? %s : ", 
                                levels[i], values[i]))
    }
    default = if (is.null(default)) 
        "null"
    else DT:::jsValues(default)
    JS(paste0(js, default))
}

datatable(df, escape = FALSE) %>%
    formatStyle('V1',
        target = 'row',
        backgroundColor = styleEqual2(
            levels = c('Cheese<sup>1</sup>', 'Crackers'),
            values = c('gray', 'gray'),
            escape = FALSE))

在不修改源代码的情况下,有没有更好的方法?

有趣的问题。我发现了一个技巧:对 levels 参数使用列表而不是字符向量。

datatable(df, escape = FALSE) %>%
  formatStyle('V1',
              target = 'row',
              backgroundColor = styleEqual(
                levels = list('Cheese<sup>1</sup>', 'Crackers'),
                values = c('gray', 'gray')))

这样,is.character(levels)is.factor(levels)都是FALSE