angular - tables - matsortheader must be placed within a parent element with the matsort directive.
La demostración de clasificación de tabla de mat no funciona (6)
Agregar orden dentro del bloque de tiempo de espera me funciona,
<ng-container matColumnDef="oppNo">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Opportunity Number</th>
<td mat-cell *matCellDef="let element">{{element.oppNo}}</td>
</ng-container>
Si no quieres usar ganchos de lifecykle.
Estoy tratando de hacer que la clasificación de la
mat-table
trabaje localmente, y aunque puedo hacer que los datos se muestren como se espera, al hacer clic en la fila del encabezado no se ordena como en los ejemplos en línea (no sucede nada).
Estoy tratando de hacer que esta demostración funcione localmente:
https://material.angular.io/components/sort/overview
https://plnkr.co/edit/XF5VxOSEBxMTd9Yb3ZLA?p=preview
He generado un nuevo proyecto con Angular CLI, luego seguí estos pasos: https://material.angular.io/guide/getting-started
Aquí están mis archivos locales:
app.module.ts
import { BrowserModule } from ''@angular/platform-browser'';
import { NgModule } from ''@angular/core'';
import { MatSort, MatTableModule } from ''@angular/material'';
import { AppComponent } from ''./app.component'';
import { TableSortingExample } from ''./table-sorting-example'';
@NgModule({
declarations: [
AppComponent,
TableSortingExample,
MatSort
],
imports: [
BrowserModule,
MatTableModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.ts
import { Component } from ''@angular/core'';
@Component({
selector: ''app-root'',
templateUrl: ''./app.component.html'',
styleUrls: [''./app.component.css'']
})
export class AppComponent {
title = ''app'';
}
app.component.html
<div style="text-align:center">
<h1>
Welcome to {{title}}!
</h1>
<table-sorting-example></table-sorting-example>
</div>
table-sorting-example.html
<div class="example-container mat-elevation-z8">
<mat-table #table [dataSource]="dataSource" matSort>
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" -->
<!-- ID Column -->
<ng-container matColumnDef="userId">
<mat-header-cell *matHeaderCellDef mat-sort-header> ID </mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.id}} </mat-cell>
</ng-container>
<!-- Progress Column -->
<ng-container matColumnDef="progress">
<mat-header-cell *matHeaderCellDef mat-sort-header> Progress </mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.progress}}% </mat-cell>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="userName">
<mat-header-cell *matHeaderCellDef mat-sort-header> Name </mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.name}} </mat-cell>
</ng-container>
<!-- Color Column -->
<ng-container matColumnDef="color">
<mat-header-cell *matHeaderCellDef mat-sort-header> Color </mat-header-cell>
<mat-cell *matCellDef="let row" [style.color]="row.color"> {{row.color}} </mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
</div>
<!-- Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license -->
table-sorting-example.ts
import {Component, ViewChild} from ''@angular/core'';
import {DataSource} from ''@angular/cdk/collections'';
import {MatSort} from ''@angular/material'';
import {BehaviorSubject} from ''rxjs/BehaviorSubject'';
import {Observable} from ''rxjs/Observable'';
import ''rxjs/add/operator/startWith'';
import ''rxjs/add/observable/merge'';
import ''rxjs/add/operator/map'';
/**
* @title Table with sorting
*/
@Component({
selector: ''table-sorting-example'',
styleUrls: [''table-sorting-example.css''],
templateUrl: ''table-sorting-example.html'',
})
export class TableSortingExample {
displayedColumns = [''userId'', ''userName'', ''progress'', ''color''];
exampleDatabase = new ExampleDatabase();
dataSource: ExampleDataSource | null;
@ViewChild(MatSort) sort: MatSort;
ngOnInit() {
this.dataSource = new ExampleDataSource(this.exampleDatabase, this.sort);
}
}
/** Constants used to fill up our data base. */
const COLORS = [''maroon'', ''red'', ''orange'', ''yellow'', ''olive'', ''green'', ''purple'',
''fuchsia'', ''lime'', ''teal'', ''aqua'', ''blue'', ''navy'', ''black'', ''gray''];
const NAMES = [''Maia'', ''Asher'', ''Olivia'', ''Atticus'', ''Amelia'', ''Jack'',
''Charlotte'', ''Theodore'', ''Isla'', ''Oliver'', ''Isabella'', ''Jasper'',
''Cora'', ''Levi'', ''Violet'', ''Arthur'', ''Mia'', ''Thomas'', ''Elizabeth''];
export interface UserData {
id: string;
name: string;
progress: string;
color: string;
}
/** An example database that the data source uses to retrieve data for the table. */
export class ExampleDatabase {
/** Stream that emits whenever the data has been modified. */
dataChange: BehaviorSubject<UserData[]> = new BehaviorSubject<UserData[]>([]);
get data(): UserData[] { return this.dataChange.value; }
constructor() {
// Fill up the database with 100 users.
for (let i = 0; i < 100; i++) { this.addUser(); }
}
/** Adds a new user to the database. */
addUser() {
const copiedData = this.data.slice();
copiedData.push(this.createNewUser());
this.dataChange.next(copiedData);
}
/** Builds and returns a new User. */
private createNewUser() {
const name =
NAMES[Math.round(Math.random() * (NAMES.length - 1))] + '' '' +
NAMES[Math.round(Math.random() * (NAMES.length - 1))].charAt(0) + ''.'';
return {
id: (this.data.length + 1).toString(),
name: name,
progress: Math.round(Math.random() * 100).toString(),
color: COLORS[Math.round(Math.random() * (COLORS.length - 1))]
};
}
}
/**
* Data source to provide what data should be rendered in the table. Note that the data source
* can retrieve its data in any way. In this case, the data source is provided a reference
* to a common data base, ExampleDatabase. It is not the data source''s responsibility to manage
* the underlying data. Instead, it only needs to take the data and send the table exactly what
* should be rendered.
*/
export class ExampleDataSource extends DataSource<any> {
constructor(private _exampleDatabase: ExampleDatabase, private _sort: MatSort) {
super();
}
/** Connect function called by the table to retrieve one stream containing the data to render. */
connect(): Observable<UserData[]> {
const displayDataChanges = [
this._exampleDatabase.dataChange,
this._sort.sortChange,
];
return Observable.merge(...displayDataChanges).map(() => {
return this.getSortedData();
});
}
disconnect() {}
/** Returns a sorted copy of the database data. */
getSortedData(): UserData[] {
const data = this._exampleDatabase.data.slice();
if (!this._sort.active || this._sort.direction == '''') { return data; }
return data.sort((a, b) => {
let propertyA: number|string = '''';
let propertyB: number|string = '''';
switch (this._sort.active) {
case ''userId'': [propertyA, propertyB] = [a.id, b.id]; break;
case ''userName'': [propertyA, propertyB] = [a.name, b.name]; break;
case ''progress'': [propertyA, propertyB] = [a.progress, b.progress]; break;
case ''color'': [propertyA, propertyB] = [a.color, b.color]; break;
}
let valueA = isNaN(+propertyA) ? propertyA : +propertyA;
let valueB = isNaN(+propertyB) ? propertyB : +propertyB;
return (valueA < valueB ? -1 : 1) * (this._sort.direction == ''asc'' ? 1 : -1);
});
}
}
/** Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license */
¿Alguien tiene una idea de por qué aparecería como la tabla en línea pero carece de la funcionalidad de clasificación?
El nombre de matColumnDef y el nombre del valor real de * matCellDef deben ser iguales
Ejemplo:
dataSource = new MatTableDataSource(this.articleService.getAllArticles());
setTimeout(() => {
this.tableDataSource.sort = this.sort;
this.tableDataSource.paginator = this.paginator;
});
En mi caso, oppNo es el mismo para matColumnDef name y * matCellDef name y la clasificación funciona bien.
Para cualquier otra persona que pueda tener este problema: el problema fue que no leí la referencia de API correctamente en el sitio web de materiales angulares, la parte que decía que tenía que importar MatSortModule. Después de cambiar mi lista de importaciones en app.module.ts a
imports: [
BrowserModule,
MatTableModule,
MatSortModule
],
funcionó bien
Si la tabla está dentro de * ngIf, no funcionará. Funcionará si se cambia a [oculto]
También llegué a este problema.
Como debe esperar a que se defina el elemento secundario, debe implementar y usar
AfterViewInit
, no onInit.
ngAfterViewInit (){
this.dataSource.sort = this.sort;
}
Tuve un problema de que la función de clasificación funcionaba pero no se ordenaba correctamente.
Me di cuenta de que
matColumnDef
debe tener el mismo nombre de la propiedad de mi
class / interface
que estoy haciendo referencia en
matCellDef
.
De acuerdo con la documentation material angular:
De manera predeterminada, MatTableDataSource ordena con el supuesto de que el nombre de la columna ordenada coincide con el nombre de la propiedad de datos que muestra la columna.
Por ejemplo:
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef mat-sort-header> NAME </mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.name}} </mat-cell>
</ng-container>
El
name
en la directiva
matColumnDef
debe ser el mismo que el
name
utilizado en el componente
<mat-cell>
.