闪亮的数据表页脚回调总和

shiny DataTables footer Callback sums

我正在为 DataTables 在一个类似于 this example from the DataTables forum. My thought so far from reading the DT documentation 的应用程序中为 DataTables 实现一个 callback 函数(第 4.4 节),它可能会通过 optionscolumnDefs 参数应用相同的 class sum,如下所示,但如果我只知道将 JS 参数放在哪里来执行 classes 像 link 中那样手动。

您可以删除所有 columnDefscallback 参数以查看示例起点。

app.R

library(shiny)
library(DT)

ui <- fluidPage(

  title = 'Select Table Rows',

  hr(),

  h1('A Server-side Table'),

  fluidRow(
    column(9, DT::dataTableOutput('x3'))
  )

)


server <- function(input, output, session) {

  # server-side processing
  mtcars2 = mtcars[, 1:8]
  output$x3 = DT::renderDataTable(DT::datatable(mtcars2, 
                                                extensions = 'Buttons',
                                                options = list(
                                                  scrollX = TRUE,
                                                  scrollY = TRUE,
                                                  pageLength = 10,
                                                  order = list(list(1, 'asc')),
                                                  fixedHeader = TRUE,
                                                  dom = 'Blrtip',
                                                  buttons = c('copy', 'csv', 'excel', 'pdf', 'print')
                                                #  columnDefs = JS("[
                                                #                  { className: 'sum', 'targets': [ 1,2 ] }
                                                #                  ]") 
                                                #  ),
                                                #callback =  JS(
                                                #  " function(row, data, start, end, display) {
                                                #  var api = this.api();
                                                #  
                                                #  api.columns('.sum', { page: 'current' }).every(function () {
                                                #  var sum = api
                                                #  .cells( null, this.index(), { page: 'current'} )
                                                #  .render('display')
                                                #  .reduce(function (a, b) {
                                                #  var x = parseFloat(a) || 0;
                                                #  var y = parseFloat(b) || 0;
                                                #  return x + y;
                                                #  }, 0);
                                                #  console.log(this.index() +' '+ sum); //alert(sum);
                                                #  $(this.footer()).html(sum);
                                                #  });
                                    #}"
                          )       
                )
      )
  }

shinyApp(ui = ui, server = server)

最终解决方案:

library(shiny)
library(DT)

ui <- fluidPage(

  title = 'Select Table Rows',

  hr(),

  h1('A Server-side Table'),

  fluidRow(
    column(9, DT::dataTableOutput('x3'))
  )

)


server <- function(input, output, session) {

  # server-side processing

  mtcars2 = mtcars[, 1:8]

  sketch <- htmltools::withTags(table(
                  class = "display",
                  style = "bootstrap",
                  tableHeader(colnames(mtcars2)),
                  tableFooter(colnames(mtcars2))
          ))

  output$x3 = DT::renderDataTable(DT::datatable(mtcars2,
                                                container = sketch,
                                                extensions = 'Buttons',
                                                options = list(
                                                  scrollX = TRUE,
                                                  scrollY = TRUE,
                                                  pageLength = 10,
                                                  order = list(list(1, 'asc')),
                                                  dom = 'Blrtip',
                                                  buttons = c('copy', 'csv', 'excel', 'pdf', 'print'),
                                                  footerCallback = JS(
       "function( tfoot, data, start, end, display ) {",
       "var api = this.api(), data;",
        "total = api.column( 1, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
        "total1 = api.column( 2, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
       "total2 = api.column( 3, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
        "total3 = api.column( 4, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
       "total4 = api.column( 5, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
        "total5 = api.column( 6, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
       "total6 = api.column( 7, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
        "total7 = api.column( 8, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
        "$( api.column( 1 ).footer() ).html(total.toFixed(2));
        $( api.column( 2 ).footer() ).html(total1.toFixed(2));
        $( api.column( 3 ).footer() ).html(total2.toFixed(2));
        $( api.column( 4 ).footer() ).html(total3.toFixed(2));
        $( api.column( 5 ).footer() ).html(total4.toFixed(2));
        $( api.column( 6 ).footer() ).html(total5.toFixed(2));
        $( api.column( 7 ).footer() ).html(total6.toFixed(2));
        $( api.column( 8 ).footer() ).html(total7.toFixed(2));",
        "}"
        ))
      ))
}

shinyApp(ui = ui, server = server)

我意识到这对 JS 来说可能是错误的形式,但是,在我的情况下,这最有效,因此我可以对每个选项应用不同的选项(一些货币符号、一些平均值、不同的小数精度等)。

为了在页脚中显示 sum/total,您必须向 table 添加一个容器,如下所示。我还更改了 JS 代码:下面提供的版本必须有效。不幸的是,我无法判断您的 JS 代码有什么问题,因为我不是 javascript 人。您可以使用 HTML(...) 部分来更改总和的显示方式。

server <- function(input, output, session) {

# server-side processing
  mtcars2 = mtcars[, 1:8]
      sketch = htmltools::withTags(table(tableFooter(c("",0,0,0,0,0,0,0,0))))
      output$x3 = DT::renderDataTable(DT::datatable(mtcars2, container = sketch,
                                                    extensions = 'Buttons',
                                                    options = list(
                                                      scrollX = TRUE,
                                                      scrollY = TRUE,
                                                      pageLength = 10,
                                                      order = list(list(1, 'asc')),
                                                      fixedHeader = TRUE,
                                                      dom = 'Blrtip',
                                                      buttons = c('copy', 'csv', 'excel', 'pdf', 'print')

                                                      footerCallback =  JS(
                                                    "function( tfoot, data, start, end, display ) {",
                                                    "var api = this.api();",
                                                    "$( api.column( 1 ).footer() ).html(",
                                                    "api.column( 1).data().reduce( function ( a, b ) {",
                                                    "return a + b;",
                                                    "} )",
                                                    ");",
                                                    "$( api.column( 2 ).footer() ).html(",
                                                    "api.column( 2 ).data().reduce( function ( a, b ) {",
                                                    "return a + b;",
                                                    "} )",
                                                    ");",
                                                    "$( api.column( 3 ).footer() ).html(",
                                                    "api.column( 3 ).data().reduce( function ( a, b ) {",
                                                    "return a + b;",
                                                    "} )",
                                                    ");",
                                                    "$( api.column( 4 ).footer() ).html(",
                                                    "api.column( 4 ).data().reduce( function ( a, b ) {",
                                                    "return a + b;",
                                                    "} )",
                                                    ");",
                                                    "$( api.column( 5 ).footer() ).html(",
                                                    "api.column( 5 ).data().reduce( function ( a, b ) {",
                                                    "return a + b;",
                                                    "} )",
                                                    ");",
                                                    "$( api.column( 6 ).footer() ).html(",
                                                    "api.column( 6 ).data().reduce( function ( a, b ) {",
                                                    "return a + b;",
                                                    "} )",
                                                    ");",
                                                    "$( api.column( 7 ).footer() ).html(",
                                                    "api.column( 7 ).data().reduce( function ( a, b ) {",
                                                    "return a + b;",
                                                    "} )",
                                                    ");",
                                                    "$( api.column( 8 ).footer() ).html(",
                                                    "api.column( 8 ).data().reduce( function ( a, b ) {",
                                                    "return a + b;",
                                                    "} )",
                                                    ");",
                                                    "}")
                                                )       
  )
  )
}

我精心设计了此函数作为有关总计和格式的可能解决方案。如果您需要 运行 一个复杂的操作,只需 运行 之前的代码,然后插入值作为 operation = "custom"。希望对你有帮助。

library(DT)
dat <- iris[1:4]

sketch <- htmltools::tags$table(
  tableHeader(names(dat)),
  tableFooter(rep("", ncol(dat))))

js_op <- function(column, operation, name = "", signif = 3) {

      # Auxiliar function for mean
      aux <- ifelse(
        operation == "mean", 
        paste0("map(function(num) { return num/data.length; })."), "")

      # Decimals to consider
      signif <- 10^signif

      # Operation
      if (operation %in% c("sum", "mean"))
        operation <- paste0("Math.round((a+b)*",signif,")/",signif)
      if (operation == "count")
        operation <- "data.length"
      if (operation == "custom")
        return(paste0("$(api.column(", column, ").footer()).html('", name, "')"))

      # Result
      res <- paste0(
        "$(api.column(", column, ").footer()).html('", name, "'+",
        "api.column(", column, ").data().", aux, "reduce( function ( a, b ) {",
        "return ", operation, ";",
        "} ));")  
      return(res)
    }

javascript <- JS(
      "function(tfoot, data, start, end, display ) {",
      "var api = this.api(), data;",
      js_op(0, operation = "count", name = "Counter: "),
      js_op(1, operation = "sum", name = "Sum: "),
      js_op(2, operation = "mean", name = "Mean: "),
      js_op(3, operation = "custom", name = "Something"),
      ";}")

datatable(iris[,1:4], rownames = FALSE, container = sketch, 
              options = list(footerCallback = javascript))