如何在reactable的汇总行与表尾中正确渲染内嵌条形图
问题根因
- 第一处错误是手写HTML的内联样式格式不符合规范:CSS属性和值的配对之间必须用**分号
;**分隔,你之前写的style属性里display:flex alignItems:center、flexGrow:1 marginLeft:8px background:#e1e1e1这类写法没有加分号,浏览器无法正确解析样式,导致元素布局完全失效。 - 第二处错误是条形图实现的边界逻辑缺失:你参考的写法给填充条加了固定padding,当width为0%时padding依然会占据空间,就会出现0值也显示部分色块的问题。
- 第三处细节问题:JS拼接HTML时的转义写法冗余,不需要给对象key加反斜杠转义单引号,直接写正常的对象取值语法即可。
可直接运行的修复方案
核心思路是统一普通单元格、聚合行、表尾的条形图渲染逻辑,严格遵循CSS语法规范,增加0值边界判断:
library(reactable) library(htmltools) library(dplyr) # R端普通单元格用的条形图函数,和官方示例样式保持一致 bar_chart <- function(label, width = "100%", height = "16px", fill = "#fc5185", background = "#e1e1e1") { bar <- div(style = list(background = fill, width = width, height = height)) chart <- div(style = list(flexGrow = 1, marginLeft = "8px", background = background), bar) div(style = list(display = "flex", alignItems = "center"), label, chart) } # 数值列通用格式化定义 formata_coluna <- colDef( aggregate = "sum", footer = function(values) format(sum(values), big.mark = '.', decimal.mark = ','), format = colFormat(separators = TRUE, digits = 0, locales = 'pt-BR') ) # JS端通用条形图渲染逻辑,聚合行、表尾共用,自动处理0值、样式格式 js_render_bar <- " function renderPercBar(sold, total) { // 处理分母为0、值为0的边界场景 const perc = total === 0 ? 0 : (sold / total * 100) const widthVal = perc.toFixed(0) + '%' const label = perc.toFixed(0) + '%' // 所有CSS属性之间必须加分号,去掉多余padding避免0值异常 return `<div style='display:flex;align-items:center;'> ${label} <div style='flex-grow:1;margin-left:8px;background:#e1e1e1;'> <div style='background:#fc5185;width:${widthVal};height:16px;'></div> </div> </div>` } " # 分组聚合行的百分比条形图渲染 grupos_perc <- JS(paste0(" function(values, rows) { let total_total = 0 let total_ocupadas = 0 rows.forEach(function(row) { total_total += row['Total'] total_ocupadas += row['Sold'] }) ", js_render_bar, " return renderPercBar(total_ocupadas, total_total) } ")) # 表尾总计的百分比条形图渲染 totais_perc <- JS(paste0(" function(column, state) { let total_total = 0 let total_ocupadas = 0 state.data.forEach(function(row) { total_total += row['Total'] total_ocupadas += row['Sold'] }) ", js_render_bar, " return renderPercBar(total_ocupadas, total_total) } ")) # 生成测试数据并渲染表格 expand.grid(Seller = LETTERS[1:3], Product = letters[1:3]) %>% mutate(Sold = rpois(9, 50), Total = Sold + rpois(9, 10), Perc = Sold/Total) %>% bind_rows(data.frame(Seller = 'D', Product = 'd', Sold = 0, Total = 10, Perc = 0)) %>% reactable( groupBy = "Seller", columns = list( Seller = colDef(footer = "Total"), Sold = formata_coluna, Total = formata_coluna, Perc = colDef( cell = function(value) { width <- paste0(value * 100, "%") bar_chart(sprintf('%.0f%%', round(value * 100, 0)), width = width) }, footer = totais_perc, aggregate = grupos_perc, html = TRUE ) ), pagination = F )
关键修复点
- 所有内联style属性的CSS规则之间都补全了分号,保证样式可以被浏览器正常解析
- 增加了分母为0的边界判断,避免出现除以0的NaN异常
- 去掉了填充条上多余的padding设置,0值时填充条宽度为0%,不会出现多余色块
- 抽离了公共的JS条形图渲染逻辑,保证普通行、聚合行、表尾的条形图样式完全一致
- 保留
html = TRUE配置,确保聚合和表尾返回的HTML字符串不会被转义成纯文本
内容的提问来源于stack exchange,提问作者Rcoster
相关产品推荐
相关产品推荐

