Angular独特すぎていつまで経ってもよくわからないし、さらに輪をかけてAngular Materialもよくわからない
デザインが変わるからTailwindみたいなCSSフレームワークと同じ感覚で使ってしまっていてわけわからんって感じになっていて、そうじゃないと理解できると意味わかるという感じ
そういうCSSフレームワーク的な理解でMatTableにソート付けたくて難儀したってことをメモしていきたい
ソート付けるためには
テーブルにソート動作を追加するには、 matSort ディレクティブをテーブルに追加し、ソートをトリガする各列ヘッダセルに mat-sort-header を追加します。 matSort ディレクティブを初期化するには、MatSortModule をインポートする必要があることに注意してください (API ドキュメントを参照してください)。
こういうこと
<table matSort (matSortChange)="sortData($event)"> <tr> <th mat-sort-header="name">Dessert (100g)</th> <th mat-sort-header="calories">Calories</th> <th mat-sort-header="fat">Fat (g)</th> <th mat-sort-header="carbs">Carbs (g)</th> <th mat-sort-header="protein">Protein (g)</th> </tr>
やってみた
matSortやsort-header付けただけだと画面上なんの変更もない
MatSortModuleをimportすると矢印がつく(もちろんソートはされない)
テーブルのデータソースに MatTableDataSource を使用している場合、データソースに MatSort ディレクティブを指定すると、ソートの変更を自動的にリッスンし、テーブルによってレンダリングされるデータの順序を変更します。
デフォルトでは、MatTableDataSource は、ソートされた列の名前が、列が表示するデータ・プロパティ名と一致することを前提としてソートします。 例えば、以下の列定義は position という名前で、行セルに表示されるプロパティの名前と一致します。
MatTableDataSourceとはなにか
DataSourceを拡張したもので、クライアント側のデータ配列を受け入れ,フィルタリング,(MatSort を用いた)ソート,(MatPaginator を用いた)ページ分割をネイティブにサポートするデータソース
sortingDataAccessor をオーバーライドすることで、 ソートのカスタマイズが可能になります。 また、filterPredicate をオーバーライドすることで、 フィルタのカスタマイズも可能になります。これは、フィルタマッチのために行データをどのように文字列に変換するかを定義します。
注意: このクラスは使い始めるためのシンプルなデータソースです。 そのため、堅牢な国際化サポートやサーバーサイドのインタラクションのような、より高度なケースを扱うための機能は備えていません。 あなたのアプリがより高度な使用例をサポートする必要がある場合は、独自のDataSourceを実装することを検討してください。
要は、MatTableDataSourceにすると自動的にソートとかフィルタとかなにもしなくても実装してくれてるってこと?
やってみた
してくれるが、かなりクセがある
以下ソートのドキュメント Table | Angular Material
まず、
@ViewChild(MatSort) sort: MatSort;
これをやらないとソートしてくれない
こいつの説明が何もなく唐突にサンプルに出てくる
4oくんに聞いてみた
MatSort
は、Angular Materialのソート機能を提供するためのディレクティブです。MatTable
と組み合わせて使用することで、ユーザーがテーブルの列ヘッダーをクリックすることで、その列に基づいてテーブルのデータをソートできるようにします。
基本的な使い方
- HTMLのセットアップ:
テーブルの各列ヘッダーに
mat-sort-header
ディレクティブを追加します。これにより、ソート機能が有効になります。
<table mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
</ng-container>
<!-- 他の列も同様に定義 -->
</table>
- コンポーネントでのセットアップ:
@ViewChild
デコレーターを使って、MatSort
インスタンスを取得し、それをデータソースに関連付けます。これにより、テーブルデータが自動的にソートされるようになります。
import { Component, ViewChild } from '@angular/core';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
@Component({
selector: 'app-my-table',
templateUrl: './my-table.component.html',
})
export class MyTableComponent {
displayedColumns: string[] = ['name', 'age', 'address'];
dataSource = new MatTableDataSource(ELEMENT_DATA);
@ViewChild(MatSort) sort: MatSort;
ngAfterViewInit() {
this.dataSource.sort = this.sort;
}
}
### @ViewChildについて
-
@ViewChild(MatSort) sort: MatSort;
は、AngularのViewChild
デコレーターを使って、MatSort
ディレクティブのインスタンスを取得しています。 -
@ViewChild
は、Angularがテンプレート内の特定のコンポーネントやディレクティブへの参照をコンポーネントクラスに注入するための機能です。この場合、MatSort
ディレクティブのインスタンスがsort
というプロパティに割り当てられます。 -
ngAfterViewInit
ライフサイクルフックでthis.dataSource.sort = this.sort;
を設定することで、テーブルデータがMatSort
と連携して動作するようになります。
なぜ@ViewChild
が必要なのか
@ViewChild
を使用する理由は、MatSort
はテンプレート内に宣言されているため、コンポーネントクラス内で直接参照できないからです。@ViewChild
を使うことで、テンプレートに存在するMatSort
ディレクティブをクラス内で操作できるようになります。
まとめ
MatSort
を使用するためには、HTMLでmat-sort-header
を各列ヘッダーに追加し、コンポーネントクラスで@ViewChild
を使ってMatSort
を取得し、データソースに関連付ける必要があります。このプロセスにより、テーブル内のデータを簡単にソートできるようになります。
参考ページ: Angular Material Sort Overview
↑ テンプレに設定してるMatSort direvtiveにアクセスするためにViewChildがいるってことらしい
direvtiveってテンプレでしか使ったことなくて、directiveのメソッドにアクセスしてなんかしたいってことなかったから考えもしなかったど、こういうケースで使えるってことなのか、これはすごい勉強になる
this.dataSource.sort = this.sort;
これをすることでソートされる
ここまでやってやっと気づいたのが、mat-tableとかこいつらディレクティブでコンポーネントでもなんでもないってことで、これ付けたらCSSが変わって見た目が変わるって理解しかしてなかったけど(まあそうなんだけど)、ディレクティブだから内部でよろしくやって見た目変えてたんだなと
これが理解できたらたしかに公式にちゃんと書いてあるわ…って感じであって、理解って大事だなと思いました