带嵌套对象的Angular Material 2数据表排序
我有一个带排序标题的普通角度材质2数据表。 所有排序都很好。除了以对象作为值的对象。 这些根本不分类 例如:带嵌套对象的Angular Material 2数据表排序,angular,angular-material2,Angular,Angular Material2,我有一个带排序标题的普通角度材质2数据表。 所有排序都很好。除了以对象作为值的对象。 这些根本不分类 例如: @ViewChild(MatSort) sort: MatSort; ngOnInit() { this.dataSource = new MatTableDataSource(yourData); this.dataSource.sortingDataAccessor = (item, property) => { switch(property) {
@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;
}
项目名称
{{element.project.name}
注意元素.project.name
以下是displayColumn配置:
displayedColumns = ['project.name', 'position', 'name', 'test', 'symbol'];
将'project.name'
更改为'project'
也不起作用“project['name']”
我错过了什么?这可能吗
下面是一场闪电战:
编辑:
谢谢你的回答。
我已经让它处理动态数据了。因此,我不必为每个新嵌套属性添加switch语句
以下是我的解决方案:(不需要创建扩展MatTableDataSource的新数据源)
导出类NestedObjectsDataSource扩展MatTableDataSource{
sortingDataAccessor:((数据:工作时间,SortheadeId:string)=>字符串|编号)=
(数据:工作时间,sortHeaderId:string):string | number=>{
设value=null;
if(sortHeaderId.indexOf('.')!=-1){
常量id=sortHeaderId.split('.');
值=数据[ID[0]][ID[1]];
}否则{
值=数据[sortHeaderId];
}
返回_isNumberValue(value)→Number(value):value;
}
构造函数(){
超级();
}
}
它正在尝试按元素['project.name']排序。显然元素没有这样的属性
创建扩展MatTableDatasource并支持按嵌套对象属性排序的自定义数据源应该很容易。查看material.angular.io文档中有关使用自定义源的示例。很难找到有关此的文档,但可以使用
排序数据访问器和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;
}
我也有同样的问题,通过测试第一个命题,我发现了一些错误,我可以通过添加“switch(property)”来修复它
您可以在组件中编写一个函数来从对象中获取属性。然后在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>
{{col.title}}
{{getProperty(行,列名称)}
我为多个嵌套对象级别进行了自定义
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;
};
我使用了一种通用方法,它允许您使用带有mat sort header
或matColumnDef
的dot.separated.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;
给出的答案甚至可以缩短,不需要切换,只要字段使用点符号
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;
}
另一种选择是,没有人在这里扔,先把柱子压平
yourData.map((d) =>
d.flattenedName = d.project && d.project.name ?
d.project.name :
'Not Specified');
this.dataSource = new MatTableDataSource(yourData);
只是另一种选择,各有利弊 我喜欢@Hieu\u-Nguyen解决方案。我只想补充一点,如果您像我一样在项目中使用lodash,那么解决方案将转化为:
import * as _ from 'lodash';
this.dataSource.sortingDataAccessor = _.get;
无需重新设计深度属性访问。使用MatTableDataSource
检查完整的MatSort问题解决方案
在HTML中
<ng-container matColumnDef="createdDate" @bounceInLeft>
<th mat-header-cell *matHeaderCellDef mat-sort-header class="date"> Created date
</th>
<td mat-cell *matCellDef="let element" class="date"> {{element.createdDate
| date :'mediumDate'}} </td>
</ng-container>
<ng-container matColumnDef="group.name">
<th mat-header-cell *matHeaderCellDef mat-sort-header class="type"> Group </th>
<td mat-cell *matCellDef="let element" class="type"> {{element.group.name}} </td>
</ng-container>
@ViewChild(MatSort, { static: true }) 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;
}
创建日期
{{element.createdDate
|日期:'mediumDate'}
团体
{{element.group.name}
@ViewChild(MatSort,{static:true})sort:MatSort;
恩戈尼尼特(){
this.dataSource=新MatTableDataSource(yourData);
this.dataSource.sortingDataAccessor=(项、属性)=>{
交换机(属性){
案例“project.name”:返回item.project.name;
默认值:返回项[属性];
}
};
this.dataSource.sort=sort;
}
只需将其添加到数据源中,您就可以访问嵌套对象
this.dataSource.sortingDataAccessor = (item, property) => {
// Split '.' to allow accessing property of nested object
if (property.includes('.')) {
const accessor = property.split('.');
let value: any = item;
accessor.forEach((a) => {
value = value[a];
});
return value;
}
// Access as normal
return item[property];
};
如果您想要有一个具有一些扩展功能的角度材质表,例如嵌套对象的排序,请查看
我创建这个库是因为我缺少了mat table开箱即用的一些功能
高级排序类似于@Hieu-Nguyen建议的答案,但有点扩展,可以按大小写字母进行适当排序。这似乎是最好的解决方案,小而简洁,而且没有开关那么有限。我真的很喜欢这个实现。减少必须使用/生成的代码。我在上次实现mat表时遇到了问题。在此之前,刷新导致了问题。不过这很干净。我也喜欢这个解决方案。我在我的项目中使用lodash
,因此如果您使用lodash
,此解决方案将转换为:this.dataSource.sortingDataAccessor=\uuu.get代码>无需重新创建深度属性访问。@andy您应该单独回答这个问题。这听起来太简单了,在评论中不可能是真的。。这就是我要做的吗?你救了我。谢谢。您是从this.dataSource.sort=sort代码>我必须将其放入ngAfterViewInit
中才能正常工作。如上面的评论所述,只需将其放入ngAfterViewInit中即可。使用“严格”类型脚本时,item[property]
将导致错误(假设item
是某种类型的对象)。对于这些情况,我发现这个答案很有用:它是关于强制一个类型化的对象是“可索引的”。当我意识到我可以返回数字或字符串时,你的解决方案对我帮助最大。我的表有两种类型,需要对数字进行排序,而不像字符串。使用检查键入的三元运算符是解决方案的关键。我得到了找不到name'\u isNumbervalue
,并且假设这是一个lodash方法,我在节点模块中找不到该方法<代码>isNumber
存在。我以前不熟悉lodash,如果这是什么。如何使用它?从“@angular/cdk/concurvation”导入{u isNumberValue};你能用fixWorks wonderfull更新stackblitz吗?但如果有