【问题标题】:shiny DataTables footer Callback sums闪亮的数据表页脚回调和
【发布时间】:2017-03-14 21:24:20
【问题描述】:

我正在努力在shiny 应用程序中为DataTables 实现callback 函数,类似于DataTables 论坛中的this example。到目前为止,我从阅读DT documentation(第 4.4 节)的想法是,可以通过options 的columnDefs 参数应用相同的类sum,如下所示,但这也是有道理的如果我只知道在哪里放置 JS 参数以手动执行类,就像在链接中一样。

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

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 来说可能是一种糟糕的形式,但是,在我的情况下,这种方式效果最好,这样我就可以对每个应用不同的选项(一些货币符号、一些平均值、不同的小数精度等)。

【问题讨论】:

  • 如果您将其发布为一个可运行的 Shiny 文件并注释掉该示例的 columDefs 参数会更好。
  • @MikeWise 谢谢,完成!
  • 我看过它,但我需要了解更多关于 DT 回调的知识才能弄清楚。

标签: r datatables shiny dt


【解决方案1】:

为了在页脚中显示总和/总计,您必须如下所示在表格中添加一个容器。我还更改了 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;",
                                                    "} )",
                                                    ");",
                                                    "}")
                                                )       
  )
  )
}

【讨论】:

  • 我认为您需要向 datatables() 添加一个“容器”参数才能正确呈现
  • 对了,我忘记写了,现在正确了,谢谢!
  • 非常感谢 Hrant - 我当时并没有意识到如何实现这一点,同时一直在学习一些 JS。 container = sketch 是绝对必要的。
【解决方案2】:

我设计了这个函数作为关于总数和格式的可能解决方案。如果您需要运行复杂的操作,只需运行之前的代码,然后将值插入为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))

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2018-11-28
  • 1970-01-01
  • 2020-02-29
  • 2019-02-18
  • 2015-09-22
  • 1970-01-01
  • 2023-03-20
  • 2021-02-13
相关资源
最近更新 更多