R闪亮包装中的父/子行 [英] Parent/Child Rows in R shiny Package

查看:38
本文介绍了R闪亮包装中的父/子行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Javascript中的背景不存在,因此诉诸于使用davlee1972在GitHub上发布的一些代码.此代码已在mtcars文件上进行了培训,然后更改为我自己的数据.

这里的问题是,尽管代码适用于前两个孩子/父母关系,但似乎只发布了最后一个孩子的列标题.

代码:

 库(data.table)图书馆(DT)图书馆(闪亮)ui<-fluidPage(fluidRow(DT :: dataTableOutput(width ="100%","table")))服务器<-功能(输入,输出){output $ table = DT :: renderDataTable({#mtcars_dt = data.table(mtcars)#setkey(mtcars_dt,mpg,cyl)#mpg_dt = unique(mtcars_dt [,list(mpg,cyl)])#setkey(mpg_dt,mpg,cyl)#cyl_dt =唯一(mtcars_dt [,list(cyl)])#setkey(cyl_dt,cyl)##mtcars_dt = mtcars_dt [,list(mtcars = list(.SD)),by = list(mpg,cyl)]#mtcars_dt [,'':='&#9658;']##mpg_dt = merge(mpg_dt,mtcars_dt,all.x = TRUE)#setkey(mpg_dt,cyl)#setcolorder(mpg_dt,c(长度(mpg_dt),c(1 :(长度(mpg_dt)-1)))))##mpg_dt = mpg_dt [,list(mpg = list(.SD)),作者= cyl]#mpg_dt [,'':='&#9658;']##cyl_dt = merge(cyl_dt,mpg_dt,all.x = TRUE)#setcolorder(cyl_dt,c(长度(cyl_dt),c(1 :(长度(cyl_dt)-1))))DT :: datatable(数据= child_1lvl,行名= FALSE,转义= -1,扩展名= c('Scroller'),选项=列表(dom ='Bfrti',autoWidth = TRUE,stripeClasses = list(),deferRender = TRUE,scrollX = TRUE,scrollY ="51vh",滚动条= TRUE,scollCollapse = TRUE,columnDefs =列表(列表(orderable = FALSE,className ='details-control',目标= 0),清单(可见=假,目标= -1))),回调= JS(table.column(1).nodes().to $().css({cursor:'pointer'})//将子对象格式化为另一个表var format = function(d){if(d!= null){var result =('< table id = \'+ d [1] +'\">< thead>< tr>').replace('.','_')for(var col in d [d.length-1] [0]){结果+ ='< th>'+ col +'</th>'}结果+ ='</tr></thead></table>'返回结果}别的{返回 '​​'}}var format_datatable = function(d){if(d!= null){if('SOME CHECK'=='最后一组儿童桌'){var subtable = $((''table#'+ d [1]).replace('.','_')).DataTable({'数据':d [d.length-1] .map(Object.values),'autoWidth':正确,'deferRender':是的,'stripeClasses':[],'信息':假,'lengthChange':否,'ordering':假,分页":错误,'scrollX':否,'scrollY':否,搜索":错误}).画()}别的{var subtable = $((''table#'+ d [1]).replace('.','_')).DataTable({'数据':d [d.length-1] .map(Object.values),'autoWidth':正确,'deferRender':是的,'stripeClasses':[],'信息':假,'lengthChange':否,'ordering':假,分页":错误,'scrollX':否,'scrollY':否,搜索":错误,'columnDefs':[{'orderable':false,'className':'details-control','targets':0},{可见":false,目标":-1}]}).画()}}}//var sub_tbl_id = 0;table.on('click','td.details-control',function(){var table = $(this).closest('table')var td = $(this)var row = $(table).DataTable().row(td.closest('tr'))如果(row.child.isShown()){row.child.hide()td.html('&#9658;')} 别的 {row.child(format(row.data())).show()format_datatable(row.data())td.html('&#9660;')}})"))},server = TRUE)}ShinyApp(ui = ui,服务器=服务器) 

生成的网页如下所示,并仅显示AccounReffullname和Fullamount标题,而不是每个财务类别下的多行.

此外,对于COGS组件,它似乎仅显示AccountReffullname列,而缺少Fullamount列.

我的问题是,它在javascript中控制子级/父级关系的层数,并且对这个为什么在mtcars文件上起作用的人是否有任何想法,但是对于我自己的数据却无法使用相同的格式.

我使用的代码发布在以下链接上:


编辑

这是一个更好的解决方案.这个不使用行内容来构建标识符.代码更简单,这允许具有相同的行.如果用户在数据集中有一个名为 details 的列,我将 details 更改为 _details .

 库(DT)## ~~多层嵌套~~ #### 数据数据<-data.frame(锶= c(1.5,2.3),说明= c("A-B","X-Y"))##第1行的详细信息subsubdat1<-data.frame(参考= c("UVW","PQR"),案例= c(99,999),stringsAsFactors = FALSE)subdat1<-data.frame(染色体="chr18",SNP ="rs2","_details" = I(list(purrr :: transpose(subsubdat1))),stringsAsFactors = FALSE,check.names =假)subdat1<-cbind(" =& oplus;",subdat1,stringsAsFactors = FALSE)##第2行的详细信息subdat2<-data.frame(染色体= c("chr19","chr20"),SNP = c("rs3","rs4"),stringsAsFactors = FALSE)##合并行详细信息subdats<-lapply(list(subdat1,subdat2),purrr :: transpose)##数据表的数据框Dat<-cbind(" =& oplus;",dat,"_details" = I(subdats))##回调回调= JS("table.column(1).nodes().to $().css({cursor:'pointer'}));",","//使嵌套表的表头","var format = function(d,childId){","if(d!= null){","var html =",'<表类= \"显示紧凑型鼠标悬停\"id = \"'+ childId +'\>< thead>< tr>';","for((d [d.length-1] [0]中的var键){","html + ='< th>'+键+'</th>';;,}","html + ='</tr></thead></table>'",返回html;"," } 别的 {","   返回 '';",}",};",","//行回调,以样式化子表的行","var rowCallback = function(row,dat,displayNum,index){","if($(row).hasClass('odd')){","$(row).css('background-color','papayawhip');","$(row).hover(function(){","$(this).css('background-color','#E6FF99');","   }, 功能() {","$(this).css('background-color','papayawhip');",});"," } 别的 {","$(row).css('background-color','lemonchiffon');","$(row).hover(function(){","$(this).css('background-color','#DDFF75');","   }, 功能() {","$(this).css('background-color','lemonchiffon');",});",}",};",","//标头回调,以样式化子表的标头","var headerCallback = function(thead,data,start,end,display){","$('th',thead).css({",'border-top':'3px solid indigo',",'color':'indigo',",'background-color':'#fadadd'",});",};",","//使数据表","var format_datatable = function(d,childId){","var数据集= [];","var n = d.length-1;","for(var i = 0; i< d [n] .length; i ++){,"var datarow = $ .map(d [n] [i],函数(值,索引){",返回[值];",});","dataset.push(datarow);",}","var id ='table#'+ childId;","if(Object.keys(d [n] [0]).indexOf('_ details')=== -1){","var subtable = $(id).DataTable({",'数据':数据集,,'autoWidth':true,",'deferRender':true,",'info':false,",'lengthChange':false,",'ordering':d [n] .length> 1,,"                '命令': [],",'paging':false,",'scrollX':false,",'scrollY':false,",'搜索':错误,",'sortClasses':false,",'rowCallback':rowCallback,",'headerCallback':headerCallback,",'columnDefs':[{targets:'_all',className:'dt-center'}]",});"," } 别的 {","var subtable = $(id).DataTable({",'数据':数据集,,'autoWidth':true,",'deferRender':true,",'info':false,",'lengthChange':false,",'ordering':d [n] .length> 1,,"           '命令': [],",'paging':false,",'scrollX':false,",'scrollY':false,",'搜索':错误,",'sortClasses':false,",'rowCallback':rowCallback,",'headerCallback':headerCallback,",'columnDefs':[,"{targets:-1,可见:false},","{targets:0,orderable:false,className:'details-control'},","{targets:'_all',className:'dt-center'}",]",}).column(0).nodes().to $().css({cursor:'pointer'});",}",};",","//在点击时显示子表","table.on('click','td.details-control',function(){","var tbl = $(this).closest('table'),","tblId = tbl.attr('id'),","td = $(this),","row = $(tbl).DataTable().row(td.closest('tr')),","rowIdx = row.index();","if(row.child.isShown()){","row.child.hide();","td.html('& oplus;');"," } 别的 {","var childId = tblId +'-child-'+ rowIdx;","row.child(format(row.data(),childId)).show();","td.html('& CircleMinus;');","format_datatable(row.data(),childId);",}",});")##数据表datatable(Dat,callback =回调,escape = -2,选项=列表(columnDefs =列表(列表(可见=假,目标= ncol(Dat)),list(orderable = FALSE,className ='details-control',目标= 1),列表(className ="dt-center",目标="_all")))) 

以下是分层数据的示例:

 库(data.table)mtcars_dt = data.table(mtcars)setkey(mtcars_dt,mpg,cyl)mpg_dt =唯一(mtcars_dt [,list(mpg,cyl)])setkey(mpg_dt,mpg,cyl)cyl_dt =唯一(mtcars_dt [,list(cyl)])setkey(cyl_dt,cyl)mtcars_dt =mtcars_dt [,list("_ details" = list(purrr :: transpose(.SD))),by = list(mpg,cyl)]mtcars_dt [,'':='& oplus;']mpg_dt = merge(mpg_dt,mtcars_dt,all.x = TRUE)setkey(mpg_dt,cyl)setcolorder(mpg_dt,c(长度(mpg_dt),c(1 :(长度(mpg_dt)-1)))))mpg_dt = mpg_dt [,list("_ details" = list(purrr :: transpose(.SD))),by = cyl]mpg_dt [,'':='& oplus;']cyl_dt = merge(cyl_dt,mpg_dt,all.x = TRUE)setcolorder(cyl_dt,c(长度(cyl_dt),c(1 :(长度(cyl_dt)-1)))))datatable(cyl_dt,回调=回调,转义= -2,选项=列表(columnDefs =列表(清单(可见=否,目标= ncol(cyl_dt)),list(orderable = FALSE,className ='details-control',目标= 1),列表(className ="dt-center",目标="_all")))) 

my background in Javascript is non - existent and therefore resorted to using some code posted by davlee1972 on GitHub. This code has been trained on the mtcars file, and was then changed to my own data.

The issue here is that whilst the code works for the first two child/parent relationships, it seems to only publish the column headings for the last child.

The code :

library(data.table)
library(DT)
library(shiny)

ui <- fluidPage(fluidRow(DT::dataTableOutput(width = "100%", "table")))

server <- function(input, output) {

output$table = DT::renderDataTable({

# mtcars_dt = data.table(mtcars)
# setkey(mtcars_dt,mpg,cyl)
# mpg_dt = unique(mtcars_dt[, list(mpg, cyl)])
# setkey(mpg_dt, mpg, cyl)
# cyl_dt = unique(mtcars_dt[, list(cyl)])
# setkey(cyl_dt, cyl)
# 
# mtcars_dt = mtcars_dt[,list(mtcars=list(.SD)), by = list(mpg,cyl)]
# mtcars_dt[, ' ' := '&#9658;']
# 
# mpg_dt = merge(mpg_dt,mtcars_dt, all.x = TRUE )
# setkey(mpg_dt, cyl)
# setcolorder(mpg_dt, c(length(mpg_dt),c(1:(length(mpg_dt) - 1))))
# 
# mpg_dt = mpg_dt[,list(mpg=list(.SD)), by = cyl]
# mpg_dt[, ' ' := '&#9658;']
# 
# cyl_dt = merge(cyl_dt,mpg_dt, all.x = TRUE )
# setcolorder(cyl_dt, c(length(cyl_dt),c(1:(length(cyl_dt) - 1))))

DT::datatable(
  data = child_1lvl,
  rownames = FALSE,
  escape = -1,
  extensions = c( 'Scroller'),
  options = list(
    dom = 'Bfrti',
    autoWidth = TRUE,
    stripeClasses = list(),
    deferRender = TRUE,
    scrollX = TRUE,
    scrollY = "51vh",
    scroller = TRUE,
    scollCollapse = TRUE,
    columnDefs = list(
      list(orderable = FALSE, className = 'details-control', targets = 0),
      list(visible = FALSE, targets = -1 )
    )
  ),
  callback = JS("
                table.column(1).nodes().to$().css({cursor: 'pointer'})



                // Format child object into another table
                var format = function(d) {
                if(d != null){ 
                var result = ('<table id=\"' + d[1] + '\"><thead><tr>').replace('.','_')
                for (var col in d[d.length - 1][0]){
                result += '<th>' + col + '</th>'
                }
                result += '</tr></thead></table>'
                return result
                }else{
                return ''
                }
                }

                var format_datatable = function(d) {
                if(d != null){
                if ('SOME CHECK' == 'LAST SET OF CHILD TABLES') {
                var subtable = $(('table#' + d[1]).replace('.','_')).DataTable({
                'data': d[d.length - 1].map(Object.values),
                'autoWidth': true, 
                'deferRender': true, 
                'stripeClasses': [],
                'info': false, 
                'lengthChange': false, 
                'ordering': false, 
                'paging': false, 
                'scrollX': false, 
                'scrollY': false, 
                'searching': false 
                }).draw()
                }else{
                var subtable = $(('table#' + d[1]).replace('.','_')).DataTable({
                'data': d[d.length - 1].map(Object.values),
                'autoWidth': true, 
                'deferRender': true,
                'stripeClasses': [],
                'info': false, 
                'lengthChange': false, 
                'ordering': false, 
                'paging': false, 
                'scrollX': false, 
                'scrollY': false, 
                'searching': false,
                'columnDefs': [{'orderable': false, 'className': 'details-control', 'targets': 0},
                {'visible': false, 'targets': -1}]
                }).draw()
                }
                }
                }



                //var sub_tbl_id = 0;
                table.on('click', 'td.details-control', function() {
                var table = $(this).closest('table')
                var td = $(this)
                var row = $(table).DataTable().row(td.closest('tr'))
                if (row.child.isShown()) {
                row.child.hide()
                td.html('&#9658;')
                } else {
                row.child(format(row.data())).show()
                format_datatable(row.data())
                td.html('&#9660;')
                }
                })




                ")
  )
},server = TRUE)
}

shinyApp (ui = ui, server = server)

the resulting webpage looks like the below and as displayed, only shows the AccounReffullname and Fullamount headings instead of the multiple rows that should be there below each financial category.

moreover, in the case of the COGS component, it only seems to show the AccountReffullname Column and is missing the Fullamount column.

My question is, where in the javascript does it control the number of layers child/parent relationships and does anyone have any idea as to why this works on the mtcars file however fails on the same format for my own data.

The code i used was posted on the following links :

https://github.com/rstudio/DT/issues/525 https://github.com/rstudio/shiny-examples/issues/9#issuecomment-362000334

Any help would be much appreciated!

thanks piyuw

解决方案

The problem with this code is that it uses the contents of the rows to build the identifiers of the child tables, and it is forbidden to use dots and white spaces in an identifier. As you can see, the child tables do not appear for rows containing a white space.

The code replaces the dots by doing replace('.','_'). This is not enough in general, because this replaces only the first occurence of a dot (with an underscore). In the code below, I replace dots and white spaces with underscores by doing replace(/[\\s|\\.]/g, '_'). The g means "global": this replaces all occurences.

To use my code, the child tables must be included in a column named "details" and this must be the last column. This code allows multiple levels of nesting: you can also define a child table for a row of a child table. In this example, the first row has a two-levels nesting.

library(DT)

## data
dat <- data.frame(
  Sr = c(1.5, 2.3),
  Description = c("A - B", "X - Y")
)
## details of row 1
subsubdat1 <- data.frame(
  Ref = c("UVW", "PQR"),
  Case = c(99, 999),
  stringsAsFactors = FALSE
)
subdat1 <- data.frame(
  Chromosome = "chr18", 
  SNP = "rs2",
  details = I(list(purrr::transpose(subsubdat1))),
  stringsAsFactors = FALSE
)
subdat1 <- cbind(" " = "&oplus;", subdat1, stringsAsFactors = FALSE)
## details of row 2
subdat2 <- data.frame(
  Chromosome = c("chr19","chr20"), 
  SNP = c("rs3","rs4"), 
  stringsAsFactors = FALSE
)

## merge the row details
subdats <- lapply(list(subdat1, subdat2), purrr::transpose)
## dataframe for the datatable
Dat <- cbind(" " = "&oplus;", dat, details = I(subdats))

## the callback
callback = JS(
  "table.column(1).nodes().to$().css({cursor: 'pointer'});",
  "// Format the nested table into another table",
  "var childId = function(d){",
  "  var tail = d.slice(2, d.length - 1);",
  "  return 'child_' + tail.join('_').replace(/[\\s|\\.]/g, '_');",
  "};",
  "var format = function (d) {",
  "  if (d != null) {",
  "    var id = childId(d);",
  "    var html = ", 
  "          '<table class=\"display compact\" id=\"' + id + '\"><thead><tr>';",
  "    for (var key in d[d.length-1][0]) {",
  "      html += '<th>' + key + '</th>';",
  "    }",
  "    html += '</tr></thead></table>'",
  "    return html;",
  "  } else {",
  "    return '';",
  "  }",
  "};",
  "var rowCallback = function(row, dat, displayNum, index){",
  "  if($(row).hasClass('odd')){",
  "    for(var j=0; j<dat.length; j++){",
  "      $('td:eq('+j+')', row).css('background-color', 'papayawhip');",
  "    }",
  "  } else {",
  "    for(var j=0; j<dat.length; j++){",
  "      $('td:eq('+j+')', row).css('background-color', 'lemonchiffon');",
  "    }",
  "  }",
  "};",
  "var headerCallback = function(thead, data, start, end, display){",
  "  $('th', thead).css({",
  "    'border-top': '3px solid indigo',", 
  "    'color': 'indigo',",
  "    'background-color': '#fadadd'",
  "  });",
  "};",
  "var format_datatable = function (d) {",
  "  var dataset = [];",
  "  var n = d.length - 1;",
  "  for (var i = 0; i < d[n].length; i++) {",
  "    var datarow = $.map(d[n][i], function (value, index) {",
  "      return [value];",
  "    });",
  "    dataset.push(datarow);",
  "  }",
  "  var id = 'table#' + childId(d);",
  "  if (Object.keys(d[n][0]).indexOf('details') === -1) {",
  "    var subtable = $(id).DataTable({",
  "                     'data': dataset,",
  "                     'autoWidth': true,",
  "                     'deferRender': true,",
  "                     'info': false,",
  "                     'lengthChange': false,",
  "                     'ordering': d[n].length > 1,",
  "                     'paging': false,",
  "                     'scrollX': false,",
  "                     'scrollY': false,",
  "                     'searching': false,",
  "                     'sortClasses': false,",
  "                     'rowCallback': rowCallback,",
  "                     'headerCallback': headerCallback,",
  "                     'columnDefs': [{targets: '_all', className: 'dt-center'}]",
  "                   });",
  "  } else {",
  "    var subtable = $(id).DataTable({",
  "                     'data': dataset,",
  "                     'autoWidth': true,",
  "                     'deferRender': true,",
  "                     'info': false,",
  "                     'lengthChange': false,",
  "                     'ordering': d[n].length > 1,",
  "                     'paging': false,",
  "                     'scrollX': false,",
  "                     'scrollY': false,",
  "                     'searching': false,",
  "                     'sortClasses': false,",
  "                     'rowCallback': rowCallback,",
  "                     'headerCallback': headerCallback,",
  "                     'columnDefs': [{targets: -1, visible: false}, {targets: 0, orderable: false, className: 'details-control'}, {targets: '_all', className: 'dt-center'}]",
  "                   }).column(0).nodes().to$().css({cursor: 'pointer'});",
  "  }",
  "};",
  "table.on('click', 'td.details-control', function () {",
  "  var tbl = $(this).closest('table');",
  "  var td = $(this),",
  "      row = $(tbl).DataTable().row(td.closest('tr'));",
  "  if (row.child.isShown()) {",
  "    row.child.hide();",
  "    td.html('&oplus;');",
  "  } else {",
  "    row.child(format(row.data())).show();",
  "    td.html('&CircleMinus;');",
  "    format_datatable(row.data());",
  "  }",
  "});")

## datatable
datatable(Dat, callback = callback, escape = -2,
          options = list(
            columnDefs = list(
              list(visible = FALSE, targets = ncol(Dat)),
              list(orderable = FALSE, className = 'details-control', targets = 1),
              list(className = "dt-center", targets = "_all")
            )
          ))


Edit

Here is a better solution. This one does not use the rows contents to build the identifier. The code is simpler and this allows to have identical rows. I have changed details to _details, in case the user has a column named details in his dataset.

library(DT)

##~~ Multiple levels of nesting ~~##

## data
dat <- data.frame(
  Sr = c(1.5, 2.3),
  Description = c("A - B", "X - Y")
)
## details of row 1
subsubdat1 <- data.frame(
  Ref = c("UVW", "PQR"),
  Case = c(99, 999),
  stringsAsFactors = FALSE
)
subdat1 <- data.frame(
  Chromosome = "chr18", 
  SNP = "rs2",
  "_details" = I(list(purrr::transpose(subsubdat1))),
  stringsAsFactors = FALSE, 
  check.names = FALSE
)
subdat1 <- cbind(" " = "&oplus;", subdat1, stringsAsFactors = FALSE)
## details of row 2
subdat2 <- data.frame(
  Chromosome = c("chr19","chr20"), 
  SNP = c("rs3","rs4"), 
  stringsAsFactors = FALSE
)

## merge the row details
subdats <- lapply(list(subdat1, subdat2), purrr::transpose)
## dataframe for the datatable
Dat <- cbind(" " = "&oplus;", dat, "_details" = I(subdats))

## the callback
callback = JS(
  "table.column(1).nodes().to$().css({cursor: 'pointer'});",
  "",
  "// make the table header of the nested table",
  "var format = function(d, childId){",
  "  if(d != null){",
  "    var html = ", 
  "      '<table class=\"display compact hover\" id=\"' + childId + '\"><thead><tr>';",
  "    for (var key in d[d.length-1][0]) {",
  "      html += '<th>' + key + '</th>';",
  "    }",
  "    html += '</tr></thead></table>'",
  "    return html;",
  "  } else {",
  "    return '';",
  "  }",
  "};",
  "",
  "// row callback to style the rows of the child tables",
  "var rowCallback = function(row, dat, displayNum, index){",
  "  if($(row).hasClass('odd')){",
  "    $(row).css('background-color', 'papayawhip');",
  "    $(row).hover(function(){",
  "      $(this).css('background-color', '#E6FF99');",
  "    }, function() {",
  "      $(this).css('background-color', 'papayawhip');",
  "    });",
  "  } else {",
  "    $(row).css('background-color', 'lemonchiffon');",
  "    $(row).hover(function(){",
  "      $(this).css('background-color', '#DDFF75');",
  "    }, function() {",
  "      $(this).css('background-color', 'lemonchiffon');",
  "    });",
  "  }",
  "};",
  "",
  "// header callback to style the header of the child tables",
  "var headerCallback = function(thead, data, start, end, display){",
  "  $('th', thead).css({",
  "    'border-top': '3px solid indigo',", 
  "    'color': 'indigo',",
  "    'background-color': '#fadadd'",
  "  });",
  "};",
  "",
  "// make the datatable",
  "var format_datatable = function(d, childId){",
  "  var dataset = [];",
  "  var n = d.length - 1;",
  "  for(var i = 0; i < d[n].length; i++){",
  "    var datarow = $.map(d[n][i], function (value, index) {",
  "      return [value];",
  "    });",
  "    dataset.push(datarow);",
  "  }",
  "  var id = 'table#' + childId;",
  "  if (Object.keys(d[n][0]).indexOf('_details') === -1) {",
  "    var subtable = $(id).DataTable({",
  "                 'data': dataset,",
  "                 'autoWidth': true,",
  "                 'deferRender': true,",
  "                 'info': false,",
  "                 'lengthChange': false,",
  "                 'ordering': d[n].length > 1,",
  "                 'order': [],",
  "                 'paging': false,",
  "                 'scrollX': false,",
  "                 'scrollY': false,",
  "                 'searching': false,",
  "                 'sortClasses': false,",
  "                 'rowCallback': rowCallback,",
  "                 'headerCallback': headerCallback,",
  "                 'columnDefs': [{targets: '_all', className: 'dt-center'}]",
  "               });",
  "  } else {",
  "    var subtable = $(id).DataTable({",
  "            'data': dataset,",
  "            'autoWidth': true,",
  "            'deferRender': true,",
  "            'info': false,",
  "            'lengthChange': false,",
  "            'ordering': d[n].length > 1,",
  "            'order': [],",
  "            'paging': false,",
  "            'scrollX': false,",
  "            'scrollY': false,",
  "            'searching': false,",
  "            'sortClasses': false,",
  "            'rowCallback': rowCallback,",
  "            'headerCallback': headerCallback,",
  "            'columnDefs': [", 
  "              {targets: -1, visible: false},", 
  "              {targets: 0, orderable: false, className: 'details-control'},", 
  "              {targets: '_all', className: 'dt-center'}",
  "             ]",
  "          }).column(0).nodes().to$().css({cursor: 'pointer'});",
  "  }",
  "};",
  "",
  "// display the child table on click",
  "table.on('click', 'td.details-control', function(){",
  "  var tbl = $(this).closest('table'),",
  "      tblId = tbl.attr('id'),",
  "      td = $(this),",
  "      row = $(tbl).DataTable().row(td.closest('tr')),",
  "      rowIdx = row.index();",
  "  if(row.child.isShown()){",
  "    row.child.hide();",
  "    td.html('&oplus;');",
  "  } else {",
  "    var childId = tblId + '-child-' + rowIdx;",
  "    row.child(format(row.data(), childId)).show();",
  "    td.html('&CircleMinus;');",
  "    format_datatable(row.data(), childId);",
  "  }",
  "});")

## datatable
datatable(Dat, callback = callback, escape = -2,
          options = list(
            columnDefs = list(
              list(visible = FALSE, targets = ncol(Dat)),
              list(orderable = FALSE, className = 'details-control', targets = 1),
              list(className = "dt-center", targets = "_all")
            )
          ))

Here is an example of hierarchical data:

library(data.table)

mtcars_dt = data.table(mtcars)
setkey(mtcars_dt, mpg, cyl)

mpg_dt = unique(mtcars_dt[, list(mpg, cyl)])
setkey(mpg_dt, mpg, cyl)

cyl_dt = unique(mtcars_dt[, list(cyl)])
setkey(cyl_dt, cyl)

mtcars_dt = 
  mtcars_dt[, list("_details" = list(purrr::transpose(.SD))), by = list(mpg,cyl)]
mtcars_dt[, ' ' := '&oplus;']

mpg_dt = merge(mpg_dt, mtcars_dt, all.x = TRUE )
setkey(mpg_dt, cyl)
setcolorder(mpg_dt, c(length(mpg_dt), c(1:(length(mpg_dt) - 1))))

mpg_dt = mpg_dt[,list("_details" = list(purrr::transpose(.SD))), by = cyl]
mpg_dt[, ' ' := '&oplus;']

cyl_dt = merge(cyl_dt, mpg_dt, all.x = TRUE )
setcolorder(cyl_dt, c(length(cyl_dt),c(1:(length(cyl_dt) - 1))))

datatable(cyl_dt, callback = callback, escape = -2,
          options = list(
            columnDefs = list(
              list(visible = FALSE, targets = ncol(cyl_dt)),
              list(orderable = FALSE, className = 'details-control', targets = 1),
              list(className = "dt-center", targets = "_all")
            )
          ))

这篇关于R闪亮包装中的父/子行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆