3

I am using angular material table 8.2.3. I have a lot of tables that are generated from a definition in the typescript. Most of the tables have to do with numbers so I have to show totals on the footer. Problem is that the material table examples in the material page have only one column and it does not show how to deal with multiple columns. I am looking for a way to dynamic calculate the sum of a column. I have the following code but it does not execute:

enter image description here

<table mat-table [dataSource]="dataSource" matSort matSortActive="Date" matSortDisableClear="true">

    <ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>{{ column.header }}</th>
        <td mat-cell *matCellDef="let row">{{ column.cell(row) }}</td>
        <td mat-footer-cell *matFooterCellDef> {{this.dataSource.data.reduce((data, val) => data+= val.cell(row), 0) </td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
    <tr mat-footer-row *matFooterRowDef="displayedColumns"></tr>
</table>
pantonis
  • 5,601
  • 12
  • 58
  • 115

2 Answers2

0

You're not writing the string interpolation syntax properly.

Your code lacks an ending }}

Here's the fixed template:

<table 
  mat-table 
  [dataSource]="dataSource" 
  matSort 
  matSortActive="Date" 
  matSortDisableClear="true">

  <ng-container 
    *ngFor="let column of columns" 
    [matColumnDef]="column.columnDef">
    <th 
      mat-header-cell 
      *matHeaderCellDef 
      mat-sort-header>
      {{ column.header }}
    </th>
    <td 
      mat-cell 
      *matCellDef="let row">
      {{ column.cell(row) }}
    </td>
    <td 
      mat-footer-cell 
      *matFooterCellDef>
      {{ dataSource.data.reduce((data, val) => data+= val.cell(row), 0) }} 
    </td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
  <tr mat-footer-row *matFooterRowDef="displayedColumns"></tr>
</table>

And then you'll probably have to make the dataSource public so that it's accessible in the template.

But considering that the dataSource is most probably, some sort of a dependency that you have in your Component, it's better to have just the data property exposed publicly.

So you might want to make a property that looks something like this:

data = this.dataSource.data.reduce((datum, val) => datum+= val.cell(row), 0);

And then where you're interpolating the result, you would do this:

<td
  mat-footer-cell
  *matFooterCellDef>
  {{ data }} 
</td>

PS - Calling methods in a Data Binding Syntax can cost a lot of performance and so it should be dealt with extreme case.

Refer to this thread if you want to know more about the consequences of calling methods in data binding syntaxes:

Angular Performance: DOM Event causes unnecessary function calls

SiddAjmera
  • 38,129
  • 5
  • 72
  • 110
  • Hi @Sidd Can we write ```this``` in template? – Siddharth Pal Dec 20 '19 at 09:26
  • @SiddharthPal, yes we can :) Try forking an Angular Stackblitz and write this in there in the template `

    {{ this | json }}

    `
    – SiddAjmera Dec 20 '19 at 09:36
  • @SiddAjmera I get ```Error: Template parse errors: Parser Error: Missing expected ) at column 29 in [ {{dataSource.data.reduce((data, val) => data+= val.cell(row), 0)}} ] in ng:///BestExecutionModule/RejectionsReportComponent.html@69:70 ("">{{ column.cell(row) }} [ERROR ->] {{dataSource.data.reduce((data, val) => data+= val.cell(row), 0)}} "):``` – pantonis Dec 20 '19 at 09:40
  • Try the latest update where I moved the whole syntax to the template and stored it in the `data` property and then used just the data property in the template. – SiddAjmera Dec 20 '19 at 09:41
  • It does not work.```Property 'cell' does not exist on type 'Client'```. I dont know if you read my entire post or just the code part. I am looking for a dynamic way to calculate table totals – pantonis Dec 20 '19 at 09:43
  • Would you mind sharing a Minimal Sample StackBlitz replicating this issue? I'd need to have a starting point to fix the issue. You can create one by **[forking this StackBlitz](https://stackblitz.com/angular/jenomxprogb?file=src%2Fapp%2Ftable-basic-example.ts)** – SiddAjmera Dec 20 '19 at 09:45
-1

I think in your example you forgot to close the {{ in <td mat-footer-cell *matFooterCellDef> {{this.dataSource.data.reduce((data, val) => data+= val.cell(row), 0) </td>

You can call function from template and calculate the sum of a column there. For example:

<td mat-footer-cell *matFooterCellDef> {{calculateSum()}} </td>

in .ts file:

calculate() {
  // calucating

  return value;
}
Kirill
  • 69
  • 5