Angular - Material - Mat-Table

Sample 1 - table

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<table mat-table [dataSource]="transactions" class="mat-elevation-z8">

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

<!-- bankAccountName Column -->
<ng-container matColumnDef="bankAccountName">
<th mat-header-cell *matHeaderCellDef> Account </th>
<td mat-cell *matCellDef="let element"> {{element.bankAccount.bankAccountName}} </td>
</ng-container>

<!-- theDate Column -->
<ng-container matColumnDef="theDate">
<th mat-header-cell *matHeaderCellDef> Date </th>
<td mat-cell *matCellDef="let element"> {{element.theDate | date : 'shortDate' }} </td>
</ng-container>

<!-- description Column -->
<ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef> Desc </th>
<td mat-cell *matCellDef="let element"> {{element.description}} </td>
</ng-container>

<ng-container matColumnDef="btn">
<th mat-header-cell *matHeaderCellDef> </th>
<td mat-cell *matCellDef="let element">
<button mat-stroked-button
(click)="onRowClicked(element)"
class='actionButton'>details
</button>
</td>
</ng-container>
</table>

Notice - this uses a table tag, and a tr tag

Notice - I removed some of the columns from the table. but you can see what’s going on.

lets talk about the first few lines

1
2
3
4
<table mat-table [dataSource]="transactions" class="mat-elevation-z8">

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

Line 1 - table tag - we are passing a datasource called transactions to the table. This is a class level variable containing a list of transactions.

Line 3 - Mat-header-row is a function that defines the header of the table. *matHeaderRowDef=”displayedColumns”. “displayedColumns” reference a class level variable that contains a list of columns to display..

Line 4 - mat-row is a function that defines the data rows of the table. *matRowDef=”let row; columns: displayedColumns;”

  • let row; - I think this starts a variable stepping through each row in the Transactions varaible list.
  • columns: displayedColumns; - this is a list of columns to display.

Here is a sample column

1
2
3
4
5
<!-- description Column -->
<ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef> Desc </th>
<td mat-cell *matCellDef="let element"> {{element.description}} </td>
</ng-container>

This defines a header, and mat-cell represents whats displayed in that column for each row in the transactions.

  • matColumnDef=”description” - this is the name of the column. In theory these ng-container tags can be in any order. But the order of columns displayed in the table is defined in that displayedColumns variable.
  • Desc is what is shown on the header row of the table.
  • mat-cell *matCellDef=”let element” - in the Row Definition we said - “let row” which setups a variable to hold the model for a row. “Let Element” - for this particular container, we are calling that object “element”
  • - this is the value to display in the column. That is the description of the propery of the object being stepped through.

There are other examples sowing buttons, and formatting of columns using the pipe operator.

The code above is part of the html for the component. Lets look at the code of the component.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
:
import { MatDialog } from '@angular/material/dialog';
import { TransactionDetailsComponent} from '../transaction-details/transaction-details.component';
import { DatePipe } from '@angular/common';
:

@Component({
selector: 'transaction-list',
templateUrl: './transaction-list.component.html',
styleUrls: ['./transaction-list.component.css']
})

export class TransactionListComponent implements OnInit {
public transactions: Transaction[]=[];

displayedColumns: string[] = ['bankAccountName', 'theDate', 'transactionType',
'vendorName','description','amount', 'accountBalance', 'btn']; //*

constructor(
private transactionService: TransactionService,
private commonService: CommonService,
public dialog: MatDialog,
private datePipe: DatePipe,
) {
}

ngOnInit() {
this.getAllTransactions();
}

public getAllTransactions() {
this.transactionService.getAllTransactions()
.subscribe(
result => {
console.log ("getAllTransactions succeeded");
console.log (result);
if (result.wasSuccessful === false) {
alert("Error trying to retrieve Transactions");
} else {
this.transactions = result.model;
}
},
error => {
alert("Error trying to retrieve Transactions!");
}
);
}

public onRowClicked(transaction: Transaction) {
console.log("row clicked: ", transaction);

const dialogRef = this.dialog.open(TransactionDetailsComponent, {
width: '80%',
data: { Transaction: transaction }
});

dialogRef.afterClosed().subscribe(result => {
console.log('The dialog was closed', result);
this.getAllTransactions();
});
}
}

In this code you can see we initialized the transactions variable with a list of transactions from the database. We also defined the displayedColumns variable and populated it with the properties we wanted to display in the table, and the order we wanted to display them.

In the above example we fixed standard html table tags and tr and td tabs. The next example uses the Material supplied code.

Sample 2 - mat-table

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<mat-table [dataSource]="markedTransactions">
<ng-container matColumnDef="theDate">
<mat-header-cell *matHeaderCellDef> Date </mat-header-cell>
<mat-cell *matCellDef="let transaction"> {{ transaction.theDate | date:'shortDate' }} </mat-cell>
</ng-container>
<ng-container matColumnDef="transactionType">
<mat-header-cell *matHeaderCellDef> Type </mat-header-cell>
<mat-cell *matCellDef="let transaction"> {{ transaction.transactionType }} </mat-cell>
</ng-container>
<ng-container matColumnDef="description">
<mat-header-cell *matHeaderCellDef> Description </mat-header-cell>
<mat-cell *matCellDef="let transaction" >
{{ transaction.description }} </mat-cell>
</ng-container>
<ng-container matColumnDef="amount">
<mat-header-cell *matHeaderCellDef> Debit </mat-header-cell>
<mat-cell *matCellDef="let transaction"> {{ transaction.amount | currency }} </mat-cell>
</ng-container>
<ng-container matColumnDef="actions">
<mat-header-cell *matHeaderCellDef> Actions </mat-header-cell>
<mat-cell *matCellDef="let trasaction">
<button mat-button color="primary"
(click)="markThis( trasaction, '0')"
matTooltip="Move entry back to Unreconciled Transactions column"
>
<mat-icon>chevron_left</mat-icon>
</button>
</mat-cell>

</ng-container>
<mat-header-row *matHeaderRowDef="columnsToDisplay"></mat-header-row>
<mat-row *matRowDef="let transaction; columns: columnsToDisplay"></mat-row>
</mat-table>

The code doesn’t change any - it’s just that we’re using material tags instead of html tags.