【问题标题】:DT::formatStyle to set background colour of datatable row based on character vector with raw HTMLDT::formatStyle 根据原始 HTML 字符向量设置数据表行的背景颜色
【发布时间】:2020-08-11 01:17:49
【问题描述】:

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

我们可以使用DT::formatStyleDT::styleEqual根据我们表中的一个变量来设置数据表特定行的背景色;比如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&lt;sup&gt;1&lt;/sup&gt;)。请注意,我们设置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&lt;sup&gt;1&lt;/sup&gt;

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

我找到了一个解决方法,它涉及修改 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))

有没有更好的方法在不修改源代码的情况下做到这一点?

【问题讨论】:

    标签: r datatables dt


    【解决方案1】:

    有趣的问题。我发现了一个窍门:为 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

    【讨论】:

    • 我喜欢你的想法!谢谢:)
    猜你喜欢
    • 1970-01-01
    • 2015-07-17
    • 1970-01-01
    • 2011-12-27
    • 1970-01-01
    • 2011-02-19
    • 1970-01-01
    • 2021-07-09
    • 2015-04-21
    相关资源
    最近更新 更多