Search code examples
jqueryslickgrid

Slickgrid grand totals


Is there a way to show grand totals in Slickgrid with grouping?

I found following:

1) In documentation Implementing a totals row via a data provider. But then I can't use DataView and grouping features.

2) There is plugin for SlickGrid called Slickgrid totals plugin. But it doesn't allow to use grouping features.


Solution

    1. Add TotalsDataProvider function
    function TotalsDataProvider(dataView, columns) {
      var totals = {};
      var totalsMetadata = {
      // Style the totals row differently.
        cssClasses: "totals",
        columns: {}
      };
      // Make the totals not editable.
      for (var i = 0; i < columns.length; i++) {
        totalsMetadata.columns[i] = { editor: null };
      }
      this.getLength = function() {
        return dataView.getLength() + 1;
      }
      this.getItem = function(index) {
        return (index < dataView.getLength()) ? dataView.getItem(index) : totals;
      };
    
      // Some group-functions from DataView
      this.setRefreshHints = function(hints) {
        return dataView.setRefreshHints(hints);
      };
      this.collapseGroup = function(varArgs) {
        return dataView.collapseGroup(varArgs);
      };
      this.expandGroup = function(varArgs) {
        return dataView.expandGroup(varArgs);
      };
    
      this.updateTotals = function() {
        var columnIdx = columns.length;
        while (columnIdx--) {
          var column = columns[columnIdx];
          if (!column.hasTotal) { // Just add in your column "hasTotal: true" 
            continue;
          }
          var total = 0;
          var i = dataView.getLength();
          while (i--) {
            total += (dataView.getItem(i)[column.field] || 0);
          }
          totals[column.field] = total;
        }
      };
      this.getItemMetadata = function(index) {
        return (index != dataView.getLength()) ? dataView.getItemMetadata(index) : totalsMetadata;
      };
      this.updateTotals();
    }
    
    1. Add option "hasTotal: true" in your columns. For example:
    var columns = [
            {id: "id", name: "Index", field: "id", hasTotal: true},
            {id: "title", name: "Title", field: "title"},
            {id: "duration", name: "Duration", field: "duration", hasTotal: true},
            {id: "%", name: "% Complete", field: "percentComplete", hasTotal: true},
            {id: "start", name: "Start", field: "start"},
            {id: "finish", name: "Finish", field: "finish"},
            {id: "effort-driven", name: "Effort Driven", field: "effortDriven"}
          ];
    
    1. Change grid variable and add dataProvider variable above:
    //grid = new Slick.Grid("#myGrid", dataView, columns, options);
    var dataProvider = new TotalsDataProvider(dataView, columns);
    grid = new Slick.Grid("#myGrid", dataProvider, columns, options);
    
    1. Every time you change data (by filtering or by grid.onCellCange) you need update total data:
    // The data has changed - recalculate the totals.
    dataProvider.updateTotals(); 
    // Rerender the totals row (last row).     
    grid.invalidateRow(dataProvider.getLength() - 1);
    grid.render();