この記事の目的
この記事は、
Angular MaterialのMat Tableを利用して、ソート処理を実装したとき、ソートがされる列とされない列ができた理由を調べること
を目的としています。
本題
Mat Tableとは
material.angular.io
リッチな機能を持つテーブルを比較簡単に実装できる素敵なテーブルだと思います。
問題となった現象
stackblitz.com
ページ上部の問題のあるテーブルと同じ現象が発生しました。具体的には、ソート順が思っていたものと違う、ソートが動かないといった現象になります。
原因と対策
原因
原因は、テーブルの列で定義する「matColumnDef」に設定する値が、DataSourceとして利用するインスタンスのプロパティ名が一致していないためでした。悪いことに、次のような組み合わせが同時に発生したことで、挙動の整理がつかなくなり、混乱したという感じでした。
- matColumnDefの値 = 想定通りの変数のプロパティ名 -> 想定通りソートが動く。
- Sampleでいうところの、name、Symbple列
- matColumnDefの値 = 想定外の変数のプロパティ名 -> 想定通りソートが動く。
- Sampleでいうところの、position列
- matColumnDefの値 != 想定外の変数のプロパティ名 -> ソートが動かない。
- Sampleでいうところの、weight列
対策
シンプルに、matColumnDefとDataSourceで利用する変数のプロパティ名を一致させるのが良いと思います。
stackblitz.com
問題のあるページを修正したものが、ページ下部の問題のないテーブルになります。
補足:Column名とデータソースのプロパティを一緒にしたくない場合
そんなケースがあるのかわからないですが、もし、こんなケースがあった場合はsortingDataAccessor で、ソートの設定を変更することができます。下記の例は、header名(matColumnDef)がnameの場合、データソースのNameプロパティを返すように”明示的に”設定していることになります。returnの値を変えれば、例えばname列をweightでソートすることができます。表示名の他に、IDやらCodeといった裏で持つ値の順番でソートしたいという用件で使えそうですね・・・しらんけど。
this.dataSource.sortingDataAccessor = ( item: PeriodicElement, header: string ) => { switch (header) { case "name": return item.name; default: return 0; } };
補足:ソート順序をカスタマイズする場合
matColumnDef列と、プロパティ名の違いという観点ではなく、ソート順をカスタマイズしたいという場合にも、sortingDataAccessor が利用できるようです。下記リンクでは、松竹梅を順番にソートするように設定しています。
qiita.com
結論
displayedColumns: string[] = [ "position", "name", "weight", "symbol" ];
Display Columnsとして定義する”列名”が、テーブルにバインドする配列のプロパティと一致している場合、ソート処理の対象として自動的に認識してくれる。上記の定義の場合、テーブルのデータソースとして利用するインターフェースやクラスの定義は、以下のようになる。
export interface PeriodicElement { name: string; position: number; weight: number; symbol: string; positionName:string; }
今回の現象(ソートが動く列と動かない列がある現象)は、列名の定義と、データソースのプロパティ名が一致していないことが原因であった。(例:name列をuserNameとして定義するなど)