несколько дочерних таблиц в DT datatable

#javascript #r #datatables #dt

#javascript #r #таблицы данных #dt

Вопрос:

Я использовал информацию из https://github.com/rstudio/shiny-examples/issues/9 для создания дочерних таблиц в DT datatable. Теперь я пытаюсь расширить этот код, чтобы получить большие дочерние таблицы. Почему-то большие дочерние таблицы отображаются не так хорошо. когда я нажимаю, чтобы развернуть, я думаю, что адресуется неправильная подтаблица.

Ниже вы можете найти мой код:

 require(tibble)
require(tidyr)
require(dplyr)
require(DT)

bla = tibble(' '='amp;oplus;', name=c("N", "Unbefristet", "Befristet", "keine Angabe"),
         val = c(2001, "85.72 %", "14.19 %", "3 %"),
         bla = list(tibble(' '='amp;oplus;', name="test", val=190, bla = list(tibble(name="lol", val=120))), 
                    tibble(' '='amp;oplus;', name="lala", val="34 %", bla = list(tibble(name="lol", val=120))),
                    tibble(' '='amp;oplus;', name=c("N", "dumm", "tra", "ra"), val=c(283, "22.66 Monate", "4 %", "3 %"), bla = list(tibble(name="lol", val=120))),
                    tibble(' '='amp;oplus;', name=c("N", "dumm", "tra", "ra"), val=c(23,355,12,124), bla = list(tibble(name="lol", val=120)))))

nested_columns         <- which(sapply(bla,class)=="list") %>% setNames(NULL)
not_nested_columns     <- which(!(seq_along(bla) %in% c(1,nested_columns)))
not_nested_columns_str <- not_nested_columns %>% paste(collapse="].replace(' ', '_')   '_'   d[") %>% paste0("d[",.,"].replace(' ', '_').replace('.','_').replace('%', '_')")


callback <- paste0("
               table.column(1).nodes().to$().css({cursor: 'pointer'});
               var myid = 1
               // Format data object (the nested table) into another table
               var format = function(d, myid) {
               if(d[4] != null){
               var result = ('<table id="child_'   myid   '">').replace('.','_')   '<thead style=display:none;><tr>'
               for (var col in d[",nested_columns,"]){
               result  = '<th>'   col   '</th>'
               }
               result  = '</tr></thead></table>'
               return result
               }else{
               return '';
               }
               }

               var format_datatable = function(d, myid) {
               var dataset = [];
               for (i = 0; i <   d[",nested_columns,"]['val'].length; i  ) {
               var datarow = [];
               for (var col in d[",nested_columns,"]){
               datarow.push(d[",nested_columns,"][col][i])
               }
               dataset.push(datarow)
               }
               var subtable = $(('table#child_'   myid).replace('.','_')).DataTable({
               'data': dataset,
               'autoWidth': true, 
               'deferRender': true, 
               'info': false, 
               'lengthChange': false, 
               'ordering': false, 
               'paging': false, 
               'scrollX': false, 
               'scrollY': false, 
               'searching': false,
               'columnDefs': [{'targets': 0, 'orderable': false, 'className': 'details-control'},
               {'targets': 3, 'visible': false}] 
               });
               };
               table.on('click', 'td.details-control', function() {
               var td = $(this), row = table.row(td.closest('tr'));
               if (row.child.isShown()) {
               row.child.hide();
               td.html('amp;oplus;');
               } else if($(this).html().charCodeAt(0)==8853){
               myid  
               row.child(format(row.data(), myid)).show();
               td.html('amp;CircleMinus;');
               format_datatable(row.data(), myid)
               }
               });"
              )

datatable(
  bla,
  escape = -2, # raw HTML in column 2
  options = list(
columnDefs = list(
  list(visible = FALSE, targets = c(0,nested_columns) ), # Hide row numbers and nested columns
  list(orderable = FALSE, className = 'details-control', targets = 1) # turn first column into control column
    )
  ),
  callback = JS(callback)
)
  

Есть идеи, в чем моя ошибка в этом коде? Заранее спасибо.

Ответ №1:

Вот пример. Я надеюсь, что это поможет.

 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(" " = "amp;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(" " = "amp;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);",
  "console.log(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('amp;oplus;');",
  "  } else {",
  "    row.child(format(row.data())).show();",
  "    td.html('amp;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")
            )
          ))
  

введите описание изображения здесь

Комментарии:

1. Как мы будем обрабатывать те случаи, когда некоторые строки имеют дочерние, а некоторые нет?

Ответ №2:

Подход, который мы используем классически, — это data.frame, однако это плохой подход.

Вы должны использовать библиотеку library (data.table), а не data.frame. Также необходимо открыть браузер, чтобы увидеть результаты.