tutorial mattabledatasource example angular angular-material2

angular - example - mattabledatasource



Angular Material 2 DataTable Clasificación con objetos anidados (7)

Tengo una tabla de datos normal de material angular 2 con encabezados de clasificación. Todo tipo de encabezados funcionan bien. Excepto el que tiene un objeto como valor. Estos no se clasifican en absoluto.

Por ejemplo:

<!-- 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>

nota el element.project.name

Aquí está la configuración de la columna de visualización:

displayedColumns = [''project.name'', ''position'', ''name'', ''test'', ''symbol''];

Cambiar ''project.name'' a ''project'' no funciona ni "project[''name'']"

¿Qué me estoy perdiendo? ¿Es esto posible?

Aquí hay un Stackblitz: Angular Material2 DataTable ordenar objetos

Edit: Gracias por todas sus respuestas. Ya lo tengo trabajando con datos dinámicos. Por lo tanto, no tengo que agregar una declaración de cambio para cada nueva propiedad anidada.

Aquí está mi solución: (No es necesario crear un nuevo DataSource que amplíe MatTableDataSource)

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(); } }


Fue difícil encontrar documentación sobre esto, pero es posible usando sortingDataAccessor y una instrucción switch. Por ejemplo:

@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; }


La respuesta que se proporciona se puede acortar, sin necesidad de cambiar, siempre y cuando use la notación de puntos para los campos.

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; }


Personalicé para múltiples niveles de objetos anidados.

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; };


Puede escribir una función en el componente para obtener una propiedad profunda del objeto. Luego, utilícelo en dataSource.sortingDataAccessor como a continuación

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''} ];

Y en 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>


Se trata de ordenar por elemento [''project.name'']. Obviamente el elemento no tiene tal propiedad.

Debería ser fácil crear una fuente de datos personalizada que amplíe MatTableDatasource y admita la clasificación por propiedades de objetos anidados. Consulte los ejemplos en documentos de material.angular.io sobre el uso de una fuente personalizada.


Tuve el mismo problema, al probar la primera proposición tuve algunos errores, podría solucionarlo agregando "switch (propiedad)"

this.dataSource.sortingDataAccessor =(item, property) => { switch (property) { case ''project.name'': return item.project.name; default: return item[property]; } };


Utilizo un método genérico que le permite usar un dot.seperated.path con mat-sort-header o matColumnDef . Esto falla de forma silenciosa y vuelve indefinido si no puede encontrar la propiedad dictada por la ruta.

function pathDataAccessor(item: any, path: string): any { return path.split(''.'') .reduce((accumulator: any, key: string) => { return accumulator ? accumulator[key] : undefined; }, item); }

Solo necesitas configurar el acceso a los datos.

this.dataSource.sortingDataAccessor = pathDataAccessor;