angular - MatTable con Sort no parece ordenar la columna
Tengo un diseño simple con el que estaba trabajando. En el archivo del módulo, he agregado las importaciones: MatSortModule y MatTableModule. Al mirar el componente que creé, era simple:
<table mat-table [dataSource]="dataSource"
matSort>
<ng-container matColumnDef="interface"> <!-- vvv This area may have some importance vvv -->
<th mat-header-cell *matHeaderCellDef mat-sort-header id="interface">Interface</th>
<td mat-cell *matCellDef="let element"><span>{{element.interface}}</span></td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
y luego el archivo TS:
class GridComponent {
dataSource = null
displayedColumns = ["interface"];
@ViewChild(MatSort, {static: true}) sort: MatSort;
@Input() set data(val: any[]) {
this._data = val;
getInfo();
}
get data () { return this._data; }
private _data: any[];
ngOnInit() {
this.dataSource = new MatTableDataSource([])
this.dataSource.sort = this.sort
}
getInfo() {
this._service.get(this._data).subscribe( data => {
/// For the ease of understanding. assume data is defined below.
const arr = [{"interface":"foo"},{"interface":"bar"}]
this.dataSource = new MatTableDataSource(arr)
this.dataSource.sort = this.sort
});
}
}
La cuadrícula muestra todas las filas, y el botón de alternancia muestra etc. Sin embargo, cuando lo alterno, la información no se reordena.
¿Hay algo que me estoy perdiendo? Vi algunos ejemplos que decían que necesitaba hacer: this.dataSource.sort=this.sort pero realmente no entiendo ese propósito y si de alguna manera está interfiriendo con el mecanismo de ordenación.
Al mirar el ejemplo de código en la parte inferior de: https://material.angular.io/components/sort/overview, me confundí ya que no vi ningún tipo de ID siendo usado, o asignado a la propiedad mat-sort-header, pero en parte de la API se afirmaba que había que hacer eso
Me encantaría algo de aclaración.
Editar: Estoy buscando una respuesta dinámica, una que me permita cambiar fácilmente los datos en la fuente de datos. En este momento, más allá del alcance del problema, tengo un input que me permite cambiar el arreglo de datos asociado con la fuente de datos, así que estoy trabajando para mantenerlo encapsulado de tal manera que pueda manejar la configuración de propiedades fuera de los inicializadores de los componentes.
Respuesta #1
Hay un cambio incorporado para matSort que puedes capturar para manejar la ordenación. Esto evita las líneas: this.dataSource.sort=this.sort;. Así que puedes eliminar todo ese código.
<table mat-table
[dataSource]="dataSource"
matSort
(matSortChange)="sortData($event)"></table>
y luego en el código puedes poner:
sortData(sort: Sort){
// Sort sorts the current list, but it wasnt updating it unless i reassigned.
this.dataSource.data = this.dataSource.data.sort((a, b) => {
const isAsc = sort.direction === 'asc';
return this._compare(a[sort.active], b[sort.active], isAsc);
});
}
private _compare(a: number | string, b: number | string, isAsc: boolean) {
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}
La otra respuesta no funcionaba en absoluto para mí, pero ahora, todo fluye bien.
Dado que hay 3 estados para sort.direction, 'asc', 'desc' y '', para la cadena vacía, establecería datasource igual al orden original de la lista.
Aquí está el componente modificado, con áreas comentadas que ahora se pueden eliminar
class GridComponent {
/// Initialize the datasource we will be augmenting its inner data.
dataSource: MatTableDataSource<any> = new MatTableDataSource();
displayedColumns = ["interface"];
//@ViewChild(MatSort, {static: true}) sort: MatSort;
@Input() set data(val: any[]) {
this._data = val;
getInfo();
}
get data () { return this._data; }
private _data: any[];
ngOnInit() {
//this.dataSource = new MatTableDataSource([])
//this.dataSource.sort = this.sort
}
getInfo() {
this._service.get(this._data).subscribe( data => {
/// For the ease of understanding. assume data is defined below.
const arr = [{"interface":"foo"},{"interface":"bar"}]
/// Updated the below line to just update data.
this.dataSource.data = arr;
//this.dataSource.sort = this.sort
});
}
sortData(sort: Sort){
// Sort sorts the current list, but it wasnt updating it unless i reassigned.
this.dataSource.data = this.dataSource.data.sort((a, b) => {
const isAsc = sort.direction === 'asc';
return this._compare(a[sort.active], b[sort.active], isAsc);
});
}
private _compare(a: number | string, b: number | string, isAsc: boolean) {
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}
}
Respuesta #2
Sí, para que la ordenación funcione en la tabla de datos mat necesitarás usar this.dataSource.sort=this.sort dentro de ngOnInit()
ngOnInit() {
this.dataSource = new MatTableDataSource<FooModel>(foobar);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
Observe cómo se puede actualizar la fuente de datos desde su suscripción de servicio:
this.fooService.getFoobar(this.isFoo).subscribe((foobar: Foo[]) => {
if (foobars != null) {
this.dataSource = new MatTableDataSource<Foo>(foobar);
this.dataSource.sort = this.sort;
