title: shiny DataTables footer Callback sums
body: <p>I'm working on implementing a <code>callback</code> function for <code>DataTables</code> in a <code>shiny</code> app similar to <a href="http://live.datatables.net/cuhukumu/2/edit" rel="nofollow noreferrer">this example</a> from the <code>DataTables</code> forum. My thought so far from reading the <code>DT</code> <a href="http://rstudio.github.io/DT/options.html" rel="nofollow noreferrer">documentation</a> (section 4.4) was that it might be possible to apply the same class <code>sum</code> through the <code>columnDefs</code> argument of <code>options</code> as below, but it would also make sense if I just knew where to put the JS argument to do the classes manually like in the link. </p>
  
  <p>You can delete all the <code>columnDefs</code> and <code>callback</code> arguments to see an example starting point.</p>
  
  <p><em>app.R</em></p>
  
  <pre><code>library(shiny)
  library(DT)
  
  ui &lt;- fluidPage(
  
    title = 'Select Table Rows',
  
    hr(),
  
    h1('A Server-side Table'),
  
    fluidRow(
      column(9, DT::dataTableOutput('x3'))
    )
  
  )
  
  
  server &lt;- 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)
  </code></pre>
  
  <p>Final solution:</p>
  
  <pre><code>library(shiny)
  library(DT)
  
  ui &lt;- fluidPage(
  
    title = 'Select Table Rows',
  
    hr(),
  
    h1('A Server-side Table'),
  
    fluidRow(
      column(9, DT::dataTableOutput('x3'))
    )
  
  )
  
  
  server &lt;- function(input, output, session) {
  
    # server-side processing
  
    mtcars2 = mtcars[, 1:8]
  
    sketch &lt;- 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)
  </code></pre>
  
  <p>I realize this is probably bad form for JS, however, in my case this works best so that I can apply different options to each (some currencies symbols, some averages, different decimal precisions etc.).</p>