ソートヘッダーを持つ通常のAngular Material 2 DataTableがあります。すべての並べ替えは、ヘッダーが正常に機能します。値としてオブジェクトを持つものを除きます。これらはまったくソートされません。
例えば:
<!-- Project Column - This should sort!-->
<ng-container matColumnDef="project.name">
<mat-header-cell *matHeaderCellDef mat-sort-header> Project Name </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.project.name}} </mat-cell>
</ng-container>
element.project.name
に注意してください
DisplayColumnの構成は次のとおりです。
displayedColumns = ['project.name', 'position', 'name', 'test', 'symbol'];
'project.name'
を'project'
に変更しても機能しません。また、"project['name']"
私は何が欠けていますか?これも可能ですか?
Stackblitzは次のとおりです。 Angular Material2 DataTable sort objects
編集:回答ありがとうございます。動的データを使用して既に動作しています。したがって、新しいネストされたプロパティごとにswitchステートメントを追加する必要はありません。
私のソリューションは次のとおりです(MatTableDataSourceを拡張する新しいDataSourceを作成する必要はありません)
export class NestedObjectsDataSource extends MatTableDataSource<MyObjectType> {
sortingDataAccessor: ((data: WorkingHours, sortHeaderId: string) => string | number) =
(data: WorkingHours, sortHeaderId: string): string | number => {
let value = null;
if (sortHeaderId.indexOf('.') !== -1) {
const ids = sortHeaderId.split('.');
value = data[ids[0]][ids[1]];
} else {
value = data[sortHeaderId];
}
return _isNumberValue(value) ? Number(value) : value;
}
constructor() {
super();
}
}
これに関するドキュメントを見つけることは困難でしたが、sortingDataAccessor
とswitchステートメントを使用することで可能です。例えば:
@ViewChild(MatSort) sort: MatSort;
ngOnInit() {
this.dataSource = new MatTableDataSource(yourData);
this.dataSource.sortingDataAccessor = (item, property) => {
switch(property) {
case 'project.name': return item.project.name;
default: return item[property];
}
};
this.dataSource.sort = sort;
}
コンポーネントから関数を作成して、オブジェクトからプロパティを深く取得できます。次に、dataSource.sortingDataAccessor
で以下のように使用します
getProperty = (obj, path) => (
path.split('.').reduce((o, p) => o && o[p], obj)
)
ngOnInit() {
this.dataSource = new MatTableDataSource(yourData);
this.dataSource.sortingDataAccessor = (obj, property) => this.getProperty(obj, property);
this.dataSource.sort = sort;
}
columnDefs = [
{name: 'project.name', title: 'Project Name'},
{name: 'position', title: 'Position'},
{name: 'name', title: 'Name'},
{name: 'test', title: 'Test'},
{name: 'symbol', title: 'Symbol'}
];
そして、html
<ng-container *ngFor="let col of columnDefs" [matColumnDef]="col.name">
<mat-header-cell *matHeaderCellDef>{{ col.title }}</mat-header-cell>
<mat-cell *matCellDef="let row">
{{ getProperty(row, col.name) }}
</mat-cell>
</ng-container>
フィールドにドット表記を使用している限り、与えられた答えは短くすることもでき、スイッチは必要ありません。
ngOnInit() {
this.dataSource = new MatTableDataSource(yourData);
this.dataSource.sortingDataAccessor = (item, property) => {
if (property.includes('.')) return property.split('.').reduce((o,i)=>o[i], item)
return item[property];
};
this.dataSource.sort = sort;
}
mat-sort-header
またはmatColumnDef
でdot.seperated.pathを使用できるようにする汎用メソッドを使用します。パスで指定されたプロパティが見つからない場合、これは暗黙的にundefinedを返すことに失敗します。
function pathDataAccessor(item: any, path: string): any {
return path.split('.')
.reduce((accumulator: any, key: string) => {
return accumulator ? accumulator[key] : undefined;
}, item);
}
データアクセサを設定するだけです
this.dataSource.sortingDataAccessor = pathDataAccessor;
複数のネストされたオブジェクトレベルにカスタマイズしました。
this.dataSource.sortingDataAccessor =
(data: any, sortHeaderId: string): string | number => {
let value = null;
if (sortHeaderId.includes('.')) {
const ids = sortHeaderId.split('.');
value = data;
ids.forEach(function (x) {
value = value? value[x]: null;
});
} else {
value = data[sortHeaderId];
}
return _isNumberValue(value) ? Number(value) : value;
};
私は同じ問題を抱えていました。いくつかのエラーがあった最初の命題をテストすることで、「スイッチ(プロパティ)」を追加することで修正できました。
this.dataSource.sortingDataAccessor =(item, property) => {
switch (property) {
case 'project.name': return item.project.name;
default: return item[property];
}
};
Element ['project.name']でソートしようとしています。明らかに要素にはそのようなプロパティはありません。
MatTableDatasourceを拡張し、ネストされたオブジェクトプロパティによる並べ替えをサポートするカスタムデータソースを簡単に作成できるはずです。 material.angular.ioのドキュメントで、カスタムソースの使用に関する例を確認してください。