Angular Material Mat Table 快速上手心得

Wai Kin Sou
6 min readDec 19, 2020

本文為介紹個人在使用ng material中的mat table上的一點心得。

我的angular版本為V11, 時間為20201219.

範例如下

index.html

架構

說明一下整個html檔的架構,

第1行的dataSource 就是資料源

第2–5,6–9行則是可以理解為兩個column 的模板(template)

第10行則是決定要顯些哪些column模板的標題(header)

第11行是決定要顯些哪些column模板的內容(Cell)

Column 模板

可以看到每個column 有3種以上的directive, 如下:

  • matColumnDef: 該column的識別Id,不能與其他column的ID重覆
<ng-container matColumnDef="age">  // columnId為age
  • matHeaderCellDef:該column的標題欄內容
<th mat-header-cell *matHeaderCellDef> Age </th> // 該column的首欄內容
  • matCellDef:顯示該column 中的cell 的內容

下面的例子中,就是宣告表格的每筆資料為people object, 該column 則顯示people的age 屬性

<td mat-cell *matCellDef="let people"> {{people.age}} </td> 

上面只有column 的模板,實際是怎樣把資料套用到模板上呢?

實際把資料套用到模板

實際上表格內容的填入是由以下的程式碼填寫的

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

matHeaderRowDef

顯示標題列(header row)中要顯示的column,displayedColumns是一個string 陣列,其中的column字串要在matColumnDef出現過

<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>displayedColumns = ['age', 'Name'];

matRowDef

決定普通資料列中要顯示的column, displayedColumns是一個string 陣列,其中的column字串要在matColumnDef出現過

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

這個例子中,matHeaderRowDef 和 matRowDef 的值剛好一樣,都是displayedColumns,實際上可以不一樣。

displayedColumns是一個string[],其中每個元素就是上面column定義的ID。舉例來說:displayedColumns = ['age', 'name'];

在顯示column標題(header)時
1. Angular會根據matHeaderRowDef 的值,即displayedColumns = [‘age’, ‘name’], 去找對應的column 模板
2. 再從對應模板中找mat-header-cell的值來顯示

如下圖

在顯示column內容時,也是一樣的步驟
1. Angular會根據matRowDef 的值去找對應的column 模板
2. 再從對應模板中找mat-cell的值來顯示

整理一下,Angular 會根據

  • matHeaderRowDef
  • matRowDef
  • matFooterRowDef (本文沒有介紹)

中定義的column陣列(例子中的displayColumns),找到該column中對應的

  • mat-header-cell
  • mat-cell
  • mat-footer-cell

來顯示。

每個mat-column只能有一個mat-header-cell、mat-cell和mat-footer-cell,第二個相同的將不會顯示。

所以若要製作多層header或多層footer,可以為每層header或footer製作各自的column。

到目前為止,應該大概明白table是怎樣長出來,接下來要介紹資料來源。

表格的資料來源 dataSource

<table mat-table [dataSource]="dataSource">
  • 最簡單的方式就是一個陣列,陣列中每個元素就是一個Object,object中的key就是column. 如上述的例子,可以提供
dataSource : Person [] = [
{Name: "peter", age: 15},
{Name: "marry", age: 20},
]
  • 第2個方法是提供一個每次都傳整個table的Observable
personSubject = new BehaviorSubject<Person[]>([]);
  • 官方推薦的方法:提供一個 DataSource類別的實例

DataSource 類別其實就一個有兩個 functions的object:

connect :dataSource接收到資料時會呼叫

disconnect : dataSource 刪除資料時會呼叫

可以自己實作

  • 官方有內建MatTableDataSource 類別, 支援內建的sort, 分頁,filter 功能

這時資料要放在data 成員上。

dataSource = new MatTableDataSource<Person[]>();
dataSource.data = [];

總結

可以看到標題列, 普通資料列中都有顯示column的設定,即用戶可以在標題列中與普通資料列中顯示不一樣的column。

用戶需在matColumnDef中定義所有column,但最後可以不顯示其中某些column。

相信明白原理後可以輕易做出新增或刪除column的功能!

refer:

  • 官方ng material mat-table文件:https://material.angular.io/components/table/overview

--

--