1

I have a mat-table that is working fine, all values display exactly in the format returned by the DB

  <mat-table #table [dataSource]="queryResults" matSort >

    <ng-container *ngFor="let column of displayedColumns" matColumnDef="{{column.name}}">
      <mat-header-cell *matHeaderCellDef mat-sort-header>{{ column.viewValue }}</mat-header-cell>
      <mat-cell *matCellDef="let item">{{item[column.name]}}</mat-cell>
    </ng-container>

    <mat-header-row *matHeaderRowDef="displayedColumnsKeys; sticky: true" ></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumnsKeys;"></mat-row>

  </mat-table>

The data structure of each item looks something like this. There are over 300 columns returned from the DB which the user can select from, so I don't want to hard code the table definition, instead I have a JSON structure that defines the columns and their values

 export interface SearchFields {
    name: string;
    viewValue: string;
    fieldType?: string;
    dispFormat?: string;
  }

Now I want to conditionaly format some values using dispFormat. Possible values of dispFormat are '' (left blank) currency or number I'm not sure how to implement a currency or number pipe, or have no formatting based on the column definition. I have tried adding *ngIf which is not correct


<mat-table #table [dataSource]="queryResults" matSort >

    <ng-container *ngFor="let column of displayedColumns" matColumnDef="{{column.name}}">
      <mat-header-cell *matHeaderCellDef mat-sort-header>{{ column.viewValue }}</mat-header-cell>
      <ng-template #currValue *ngIf="column.dispFormat=='currency'" ><mat-cell *matCellDef="let item" >{{item[column.name] | currency:'USD':true:'2.2-4'}}</mat-cell></ng-template>
      <ng-template #noFormatValue *ngIf="column.dispFormat==''" > <mat-cell *matCellDef="let item" >{{item[column.name]}}</mat-cell></ng-template>
    </ng-container>

    <mat-header-row *matHeaderRowDef="displayedColumnsKeys; sticky: true" ></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumnsKeys;"></mat-row>

  </mat-table>

But this gives errors due to mixing *ngIf and *matCellDef

ERROR TypeError: Cannot read property 'template' of undefined

How can I format the values based on a condition?

EDIT - As requested, adding sample data
Sample dataSource is:

[{name: 'Company A',
accountspayable: 172286000,
accumulatedamortization: null,
beta: 0.5718,
bookvalue: 15.128,
buy: 0},
{name: 'Company B',
accountspayable: 112676000,
accumulatedamortization: 1689965,
beta: 0.5,
bookvalue: 27.5,
buy: 1},
{name: 'Company C',
accountspayable: 126546000,
accumulatedamortization: 1889965,
beta: 0.168,
bookvalue: 10,
buy: 5}
]

Column definitions are:

[
{ name: 'name', viewValue: 'Name',dispFormat: '' },
{ name: 'accountspayable', viewValue: 'Accounts Payable', dispFormat: 'currency' },
{ name: 'accumulatedamortization', viewValue: 'Accumulated Amortization', dispFormat: 'currency' },
{ name: 'beta', viewValue: 'Beta', dispFormat: 'number' },
{ name: 'bookvalue', viewValue: 'Book Value', dispFormat: 'currency' },
{ name: 'buy', viewValue: 'Buy', dispFormat: 'number' }
]

2 Answers 2

2

I've found the answer, it's simply to put the ngIf inside the mat-cell

  <mat-table #table [dataSource]="queryResults" matSort >

    <ng-container *ngFor="let column of displayedColumns" matColumnDef="{{column.name}}">
      <mat-header-cell *matHeaderCellDef mat-sort-header>{{ column.viewValue }}</mat-header-cell>
      <mat-cell *matCellDef="let item">
        <div *ngIf="column.dispFormat=='currency'">
          {{item[column.name] | currency:'USD':true:'2.0-4'}}
        </div>
        <div *ngIf="column.dispFormat=='number'">
          {{item[column.name] | number : '2.0-4'}}
        </div>
        <div *ngIf="column.dispFormat==''">
          {{item[column.name]}}
        </div>
      </mat-cell>
    </ng-container>

    <mat-header-row *matHeaderRowDef="displayedColumnsKeys; sticky: true" ></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumnsKeys;"></mat-row>

  </mat-table>

Sign up to request clarification or add additional context in comments.

1 Comment

As you say, you can not to have two "structural directives" in the same tag (e.g. *matHeaderCellDef and *ngIf). If you don't want to create an HTML element. you can use ng-container (or move one structural directive to another element as you make)
0

You might want to try by not changing the mat table syntax:

      <mat-header-cell *matHeaderCellDef mat-sort-header>{{ column.viewValue }}</mat-header-cell>
      <ng-template #currValue *ngIf="column.dispFormat=='currency'" ><mat-cell *matCellDef="let item" >{{item[column.name] | currency:'USD':true:'2.2-4'}}</mat-cell></ng-template>
      <ng-template #noFormatValue *ngIf="column.dispFormat==''" > <mat-cell *matCellDef="let item" >{{item[column.name]}}</mat-cell></ng-template>
    </ng-container>```

could be changed to

```<ng-container *ngFor="let column of displayedColumns" matColumnDef="{{column.name}}">
      <mat-header-cell *matHeaderCellDef mat-sort-header>{{ column.viewValue }}</mat-header-cell>
      <mat-cell *matCellDef="let item" >
        <span *ngIf="column.dispFormat=='currency'">{{item[column.name] | currency:'USD':true:'2.2-4'}}</span>
        <span *ngIf="column.dispFormat==''">{{item[column.name]}}</span>
      </mat-cell>
   </ng-container>

3 Comments

thanks, but that did not work. Frst it does not compile due to error Property 'item' does not exist... so I added the mat-cell back inside the <span> then I still get the run time error Cannot read property 'template' of undefined
Could you please attach a screenshot of the result of dataSource
I've added the sample data

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.