A minimal example to get you up and running fast...
<table mat-table [dataSource]="collection">
<ng-container matColumnDef="setting">
<th mat-header-cell *matHeaderCellDef>Setting</th>
<td mat-cell *matCellDef="let setting">
{{ setting.id }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
The dataSource
The mat-table directive allows us to set a datasource...
<table mat-table [dataSource]="collection">
which is an Array of something in our Typescript file for this page.
Column Definitions
The Material Table focuses on a columnar first concept using ng-containers.
<ng-container matColumnDef="setting">
<th mat-header-cell *matHeaderCellDef>Setting</th>
<td mat-cell *matCellDef="let setting">
{{ setting.propName }}
</td>
</ng-container>
The ng-container uses the "matColumnDef" directive (a column definition) with the name of 'setting'. This column of the table will have a header with the value "Setting" shown. Each row of data will show the value of setting.propName.
At render time, each material column definition is called with each item within the dataSource. But nothing will show unless the next two items are defined.
Table Rows
The column definitions only took care of the TH and the TD for each column header. Now we have to define how to render each row. The all important displayedColumns is used as a mat-header-row and a mat-row. I'm not fully aware of why we need two TR items.
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
Here we see each TR pointing to displayedColumns which is an array of the names we assigned to each columndef we want to show.
Injecting Content Renderers
Can we swap in other custom controls? Yes..
If we substitute a custom component as in "app-setting" below, the content of the TD will pass a setting value to the app-setting html element via the [setting] property it contains.
<table mat-table [dataSource]="collection">
<ng-container matColumnDef="setting">
<th mat-header-cell *matHeaderCellDef>Setting</th>
<td mat-cell *matCellDef="let setting">
<app-setting [setting]="setting"></app-setting>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
The material table's 1st column will look like this when we name the columndef "Setting" and have only one value in:
We've injected our own rendering logic for each row of the Table.
Next up: Render HTML elements which are editable on each row of a Material Table.
JWP2020
Top comments (1)
I'm confused by the syntax of:
<tr mat-row *matRowDef="let row; columns: displayedColumns">
- what is the expression inmatRowDef
doing here exactly?