Search code examples
javascripthtmldatatable

Sum total values ​with footerCallback


I have the following code that returns the values ​​for the tbody of the table.

In this table I want to have tfoot to add the value of the last column and I'm doing it this way:

var data = [
   {Id: "1", Quantidade:  "14", Preco: "3.10", },
   {Id: "2", Quantidade: "5", Preco: "1.80", },
   {Id: "3", Quantidade: "3", Preco: "0.45", },
   {Id: "4",  Quantidade: "4", Preco: "9.83",  },
   {Id: "5", Quantidade: "2", Preco: "15.30", },
   {Id: "6",  Quantidade: "3", Preco: "9.98",  },
];

$('.enc-per').on("click", function() {

  
  var linha = ``;
  
  Object.keys(data).forEach(b => {
  
    Id = data[b].Id;
    Qtd = data[b].Quantidade;
    Preco = data[b].Preco;
    Total = data[b].Quantidade * data[b].Preco;
    
    linha += `<tr>
               <td class="text-center text-muted"> ${Id}</td>
               <td class="text-center text-muted"> ${Qtd}</td>
               <td class="text-center text-muted"> ${Preco}</td>
               <td class="text-center text-muted"> ${Total}</td>
             </tr>`;

 })
 $("#encofinal tbody").html(linha);
 
 $('.encofinal').DataTable({
   fixedHeader: {
      header: true,
      footer: true
   }, 
   footerCallback: function(){
      const sumProduct = this
        .api()
        .rows({search:'applied'})
        .data()
        .toArray()
        .reduce((res,row) => {
     const Quantidade = row[1];
     const Preco = row[2];
     return res += Quantidade*Preco}, 0).toFixed(2);
        $('#sumproduct').text(sumProduct);
   }
 });
          
          
});
<link href="https://cdn.datatables.net/1.11.4/css/dataTables.bootstrap5.min.css" rel="stylesheet">
    <link href="https://cdn.datatables.net/buttons/2.2.2/css/buttons.bootstrap5.min.css" rel="stylesheet">

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.datatables.net/1.11.4/js/jquery.dataTables.min.js"></script>
    <script src="https://cdn.datatables.net/1.11.4/js/dataTables.bootstrap5.min.js"></script>
    <script src="https://cdn.datatables.net/buttons/2.2.2/js/dataTables.buttons.min.js"></script>
    <script src="https://cdn.datatables.net/buttons/2.2.2/js/buttons.bootstrap5.min.js"></script>

<button type="button" class="btn btn-info enc-per" style="float: right; margin-right: 5%; margin-top: 4%;"><i class="metismenu-icon pe-7s-search"></i> Consultar </button>


<table class="align-middle mb-0 table table-border table-striped table-hover encofinal" id="encofinal">
  <thead>
    <tr>
      <th class="text-center">Pedido</th>
      <th class="text-center">Qtd</th>
      <th class="text-center">Preço</th>
      <th class="text-center">Valor</th>
    </tr>
  </thead>
  <tbody>
  </tbody>
  <tfoot>
    <tr>
      <td COLSPAN="2"></td>
      <td COLSPAN="3">Valor Total: <span id="sumproduct"></span>€</td>
    </tr>
  </tfoot>
</table>

But it returns the values ​​correctly, but the sum of tfoot returns error. I think the problem is sending the data to tfoot.

Can you help me solve the problem?

error console:

Uncaught TypeError: Cannot set properties of undefined (setting 'nTf')
    at Fb (jquery.dataTables.min.js:40:282)
    at Ba (jquery.dataTables.min.js:62:151)
    at f (jquery.dataTables.min.js:108:98)
    at HTMLTableElement.<anonymous> (jquery.dataTables.min.js:108:184)
    at Function.each (jquery-3.6.0.min.js:2:3003)
    at S.fn.init.each (jquery-3.6.0.min.js:2:1481)
    at S.fn.init.u [as dataTable] (jquery.dataTables.min.js:98:199)
    at HTMLButtonElement.<anonymous> (jsdashboard.js:21510:21)
    at HTMLButtonElement.dispatch (jquery-3.6.0.min.js:2:43064)
    at v.handle (jquery-3.6.0.min.js:2:41048)

Solution

  • The error is being caused by the fact that your table has an inconsistent number of columns in each row. Most have 4 but your table footer spans 5 columns (2+3):

        <tr>
          <td COLSPAN="2"></td>
          <td COLSPAN="3">Valor Total: <span id="sumproduct"></span>€</td>
        </tr>
    

    Corrected to span only 4 columns and it works:

    var data = [
       {Id: "1", Quantidade:  "14", Preco: "3.10", },
       {Id: "2", Quantidade: "5", Preco: "1.80", },
       {Id: "3", Quantidade: "3", Preco: "0.45", },
       {Id: "4",  Quantidade: "4", Preco: "9.83",  },
       {Id: "5", Quantidade: "2", Preco: "15.30", },
       {Id: "6",  Quantidade: "3", Preco: "9.98",  },
    ];
    
    $('.enc-per').on("click", function() {
    
    
      var linha = ``;
    
      Object.keys(data).forEach(b => {
    
        Id = data[b].Id;
        Qtd = data[b].Quantidade;
        Preco = data[b].Preco;
        Total = data[b].Quantidade * data[b].Preco;
    
        linha += `<tr>
                   <td class="text-center text-muted"> ${Id}</td>
                   <td class="text-center text-muted"> ${Qtd}</td>
                   <td class="text-center text-muted"> ${Preco}</td>
                   <td class="text-center text-muted"> ${Total}</td>
                 </tr>`;
    
      })
      $("#encofinal tbody").html(linha);
    
      $('.encofinal').DataTable({
        fixedHeader: {
          header: true,
          footer: true
        },
        footerCallback: function() {
          const sumProduct = this
            .api()
            .rows({
              search: 'applied'
            })
            .data()
            .toArray()
            .reduce((res, row) => {
              const Quantidade = row[1];
              const Preco = row[2];
              return res += Quantidade * Preco
            }, 0).toFixed(2);
          $('#sumproduct').text(sumProduct);
        }
      });
    
    
    });
    <link href="https://cdn.datatables.net/1.11.4/css/dataTables.bootstrap5.min.css" rel="stylesheet">
    <link href="https://cdn.datatables.net/buttons/2.2.2/css/buttons.bootstrap5.min.css" rel="stylesheet">
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdn.datatables.net/1.11.4/js/jquery.dataTables.min.js"></script>
    <script src="https://cdn.datatables.net/1.11.4/js/dataTables.bootstrap5.min.js"></script>
    <script src="https://cdn.datatables.net/buttons/2.2.2/js/dataTables.buttons.min.js"></script>
    <script src="https://cdn.datatables.net/buttons/2.2.2/js/buttons.bootstrap5.min.js"></script>
    
    <button type="button" class="btn btn-info enc-per" style="float: right; margin-right: 5%; margin-top: 4%;"><i class="metismenu-icon pe-7s-search"></i> Consultar </button>
    
    
    <table class="align-middle mb-0 table table-border table-striped table-hover encofinal" id="encofinal">
      <thead>
        <tr>
          <th class="text-center">Pedido</th>
          <th class="text-center">Qtd</th>
          <th class="text-center">Preço</th>
          <th class="text-center">Valor</th>
        </tr>
      </thead>
      <tbody>
      </tbody>
      <tfoot>
        <tr>
          <td COLSPAN="2"></td>
          <td COLSPAN="2">Valor Total: <span id="sumproduct"></span>€</td>
        </tr>
      </tfoot>
    </table>