如何在R Shiny的DT datatable中实现父行折叠展示子行功能
R Shiny DT 父子行(可变子行数)实现方案
直接运行下方完整代码即可实现需求:父ID仅展示1次,对应子行默认隐藏,点击父行可展开/收起子行,自动适配0到任意数量的子行,不需要修改JS逻辑。
依赖安装
如果没有安装所需依赖,先运行以下命令安装:
install.packages(c("shiny", "DT", "dplyr"))
完整可运行代码
library(shiny) library(DT) library(dplyr) # -------------------------- # 可替换为你自己的业务数据 # -------------------------- df = data.frame( parentID = c("parent1","parent1","parent2","parent3","parent4","parent4","parent4"), childID = c("childA","childB","childC","childD","childE","childF","childG"), childDesc = c("desc1","desc2","desc3","desc4","desc5","desc6","desc7") ) # -------------------------- # 固定预处理逻辑 无需修改 # -------------------------- parent_df = df %>% distinct(parentID) parent_df$child_data = lapply(parent_df$parentID, function(pid){ df %>% filter(parentID == pid) %>% select(-parentID) }) # -------------------------- # 固定JS回调逻辑 无需修改 # -------------------------- callback_js = JS( "table.on('click', 'td.details-control', function() {", " var tr = $(this).closest('tr');", " var row = table.row(tr);", " if (row.child.isShown()) {", " row.child.hide();", " tr.removeClass('shown');", " } else {", " row.child(format(row.data().child_data)).show();", " tr.addClass('shown');", " }", "});", "function format(d) {", " if (d.length == 0) return '<span style=\"padding-left:50px;\">无对应子行</span>';", " var table = '<table cellpadding=\"5\" cellspacing=\"0\" border=\"0\" style=\"padding-left:50px;\">'+", " '<thead><tr><th>子项ID</th><th>子项描述</th></tr></thead><tbody>';", " for (var i = 0; i < d.length; i++) {", " table += '<tr>' +", " '<td>' + d[i].childID + '</td>' +", " '<td>' + d[i].childDesc + '</td>' +", " '</tr>';", " }", " table += '</tbody></table>';", " return table;", "}" ) # -------------------------- # Shiny界面与渲染逻辑 # -------------------------- ui <- fluidPage( DTOutput("dt_table") ) server <- function(input, output) { output$dt_table = renderDT({ datatable( parent_df, rownames = FALSE, callback = callback_js, options = list( columnDefs = list( list( targets = 0, className = 'details-control', orderable = FALSE, render = JS("function(data, type, row, meta) {", " return '<span style=\"cursor:pointer;\">➕ ' + data + '</span>';", "}") ), list(targets = 1, visible = FALSE) # 隐藏存储子数据的列 ), ordering = FALSE, # 可按需删除开启排序 paging = FALSE, # 可按需删除开启分页 searching = FALSE # 可按需删除开启搜索 ) ) }, server = FALSE) } shinyApp(ui, server)
自定义修改说明
- 替换上述代码中
df为你自己的数据集即可,父分组列名保持为parentID - 如果子列不是
childID和childDesc,只需修改JS的format函数中对应的列名和表头文本即可,无需改动其他逻辑 - 默认关闭了排序、分页、搜索功能,如需要删除
options中对应的配置项即可
内容的提问来源于stack exchange,提问作者Cola4ever
相关产品推荐
相关产品推荐

