【问题标题】:Expanding and collapsing child rows in Shiny DataTable在 Shiny DataTable 中展开和折叠子行
【发布时间】:2017-04-27 20:58:08
【问题描述】:

我在 Shiny 中复制数据表对象时遇到问题。目前,当我在 Shiny 环境之外运行代码的数据表部分时,我可以显示我想要的内容。但是,当我运行整个代码时,它没有显示子表。

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

shinyApp(
 ui = fluidPage(DT::dataTableOutput('tbl')),
 server = function(input, output) {
 output$tbl = DT::renderDataTable(

  datatable({
    #Transform dataframe to data.table and turn the dataframe rowname into a data.table column called model
    mtcars_dt = data.table(mtcars)
    mtcars_dt[["model"]] = rownames(mtcars)
    setcolorder(mtcars_dt,c(
      which(colnames(mtcars_dt) %in% c("mpg","cyl","model")),
      which(!colnames(mtcars_dt) %in% c("mpg","cyl","model"))
    ))

    #Turn data table into a nested data.table by mpg, cyl
    mtcars_dt <- mtcars_dt[, list(cars=list(.SD)), by = list(mpg,cyl)]


    #configure datatable. Hide row number and cars columns [0,4] and enable details control on plus sign column[1]
    #turn rows into child rows and remove from parent
    cbind(' ' = '&oplus;', mtcars_dt)}, 

    escape = -2,
    options = list(
      columnDefs = list(
        list(visible = FALSE, targets = c(0,4)),
        list(orderable = FALSE, className = 'details-control', targets = 1)
      )
    ),
    callback = JS("
                  table.column(1).nodes().to$().css({cursor: 'pointer'});

                  // Format cars object into another table
                  var format = function(d) {
                  if(d != null){ 
                  var result = ('<table id=\"child_' + d[2] + '_' + d[3] + '\">').replace('.','_') + '<thead><tr>'
                  for (var col in d[4]){
                  result += '<th>' + col + '</th>'
                  }
                  result += '</tr></thead></table>'
                  return result
                  }else{
                  return '';
                  }
                  }

                  var format_datatable = function(d) {
                  var dataset = [];
                  for (i = 0; i < + d[4]['model'].length; i++) {
                  var datarow = [];
                  for (var col in d[4]){
                  datarow.push(d[4][col][i])
                  }
                  dataset.push(datarow)
                  }
                  var subtable = $(('table#child_' + d[2] + '_' + d[3]).replace('.','_')).DataTable({
                  'data': dataset,
                  'autoWidth': true, 
                  'deferRender': true, 
                  'info': false, 
                  'lengthChange': false, 
                  'ordering': true, 
                  'paging': false, 
                  'scrollX': false, 
                  'scrollY': false, 
                  'searching': 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('&oplus;');
                  } else {
                  row.child(format(row.data())).show();
                  td.html('&CircleMinus;');
                  format_datatable(row.data())
                  }
                  });")
      )
    )
  }
)

感谢您的帮助!

【问题讨论】:

    标签: javascript jquery r shiny datatables-1.10


    【解决方案1】:

    这里的关键似乎是对象和数组之间的区别。使用闪亮时,row.data() 是一个数组,它的第五个元素也是一个数组(这里我点击了主表的第二行):

    ["2", "&oplus;", 22.8, 4, Array(2)]
    

    在闪亮的环境之外,row.data() 看起来像这样:

    ["2", "&oplus;", 22.8, 4, Object]
    

    如您所见,第五个元素是一个对象!为什么会这样,我说不出来。我猜幕后使用的库版本可能有所不同。

    要使这项工作正常进行,我们需要进行 2 项更改:

    1.换format()


    var format = function(d) {
      if(d != null) { 
        var result = ('<table id=\"child_' + d[2] + '_' + d[3] + '\">').replace('.','_') + '<thead><tr>'
        for (var col in d[4][0]) {
           result += '<th>' + col + '</th>'
        }
        result += '</tr></thead></table>'
        return result
      } else {
        return '';
      }
    }
    

    这里我们只是在第4行添加了[0]。如上图,d[4]是一个数组。在第二行数据的情况下,它由 2 个对象组成。 (var col in d[4]) 将返回 01(对象的索引),而 (var col in d[4][0]) 返回第一个对象的元素(因此是列名)。

    2。换format_datatable()


    var format_datatable = function(d) {
      var dataset = [];
      for (i = 0; i <=  d[4].length-1; i++) {
        var datarow = $.map(d[4][i], function(value, index) {
          return [value];
        });
        dataset.push(datarow);
      }
      //  ...
      //  the rest did not change
    }
    

    这里我们使用$.map()将表示为对象的每个汽车模型(因此d[4]中的每个元素)转换为一个数组。之后我们只需将此数组添加到dataset

    创建子表的代码需要这些数组。 DataTables 对数据的处理方式不同,可以检查here

    【讨论】:

      猜你喜欢
      • 2011-01-09
      • 1970-01-01
      • 2021-08-05
      • 2016-08-25
      • 1970-01-01
      • 2018-12-13
      • 2013-06-06
      • 2014-06-30
      • 1970-01-01
      相关资源
      最近更新 更多