Search code examples
javascriptjquerydatatablescontenteditable

DataTables footerCallback and contenteditable


I have a DataTable that sums over each column using footerCallback. This works perfectly given the data in each column, but I also want to add the ability to change each cell's value that is being summed. I've tried adding "contenteditable" to those cells, but making a change does not affect the sum in the footer.

Here is a simple jsfiddle showing the behavior I'm experiencing: https://jsfiddle.net/rantoun/552y9j90/6/

HTML:

<table id="table1">
  <thead>
    <tr>
      <th>Fruit</th>
      <th># Eaten</th>
      <th># Remaining</th>
    </tr>
  </thead>
  <tfoot>
    <tr>
      <th align="right">Count</th>
      <th align="left"></th>
      <th align="left"></th>
    </tr>
  </tfoot>
  <tbody>
    <tr>
      <td>Apples</td>
      <td contenteditable>3</td>
      <td contenteditable>8</td>
    </tr>
    <tr>
      <td>Oranges</td>
      <td contenteditable>6</td>
      <td contenteditable>5</td>
    </tr>
    <tr>
      <td>Bananas</td>
      <td contenteditable>2</td>
      <td contenteditable>9</td>
    </tr>
  </tbody>
</table>

jQuery:

$("#table1").DataTable({
  "paging": false,
  "searching": false,
  "info": false,    
    "footerCallback": function ( row, data, start, end, display ) {

      var columns = [1, 2];
      var api = this.api();

      _.each(columns, function(idx) {

          var total = api
              .column(idx)
              .data()
              .reduce(function (a, b) {
                  return parseInt(a) + parseInt(b);
              }, 0)         

                $('tr:eq(0) th:eq('+idx+')', api.table().footer()).html(total);
      })

  }
});

I have also found the DataTables editor (https://editor.datatables.net/examples/inline-editing/simple), which would be perfect for this situation - but it is not open source. Any ideas on how to mimic this inline editing functionality is welcome. I would like to avoid doing this with modals. Any help is appreciated!


Solution

  • Here is an answer that allows you to edit in place with contenteditable.

    Note that this requires the dataTables KeyTable plugin

    Working Fiddle here

    /* Note - requires datatable.keys plugin */
        var table = $("#table1").DataTable({
    
          "keys": true,     
    
          "paging": false,
          "searching": false,
          "info": false,    
            "footerCallback": function ( row, data, start, end, display ) {
    
              var columns = [1, 2];
              var api = this.api();
    
              _.each(columns, function(idx) {
    
                  var total = api
                      .column(idx)
                      .data()
                      .reduce(function (a, b) {
                          return parseInt(a) + parseInt(b);
                      }, 0)         
    
                        $('tr:eq(0) th:eq('+idx+')', api.table().footer()).html(total);
              })
    
          }
        });
    
        // keys introduces the key-blur event where we can detect moving off a cell
        table
            .on( 'key-blur', function ( e, datatable, cell ) {
    
            // The magic part - using the cell object, get the HTML node value,
            // put it into the dt cell cache and redraw the table to invoke the 
            // footer function. 
                cell.data( $(cell.node()).html() ).draw()
            } );
    

    Note - I can foresee that you may get non-numeric data entered. You will have to police that in the key-blur event where you can test the dom node value and act accordingly.