정렬 헤더가있는 일반 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 정렬 개체
편집 :
모든 답변에 감사드립니다. 나는 이미 동적 데이터로 작업하고 있습니다. 따라서 새로운 중첩 속성마다 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;
}
답변
나는 @Hieu_Nguyen 솔루션을 좋아합니다. 내가 한 것처럼 프로젝트에서 lodash를 사용하면 솔루션이 다음과 같이 변환됩니다.
import * as _ from 'lodash';
this.dataSource.sortingDataAccessor = _.get;
깊은 속성 액세스를 재발 명 할 필요가 없습니다.
답변
난 당신과 함께 dot.seperated.path를 사용할 수있는 일반적인 방법을 사용 mat-sort-header
또는 matColumnDef
. 경로에 지정된 속성을 찾을 수 없으면 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;
};
답변
아무도 여기에 버리지 않은 또 다른 대안은 먼저 기둥을 평평하게 만듭니다 …
yourData.map((d) =>
d.flattenedName = d.project && d.project.name ?
d.project.name :
'Not Specified');
this.dataSource = new MatTableDataSource(yourData);
또 다른 대안, 각각의 장단점!