Ich versuche, die mat-table
Sortierung lokal zum Laufen zu bringen, und obwohl die Daten wie erwartet angezeigt werden können, führt das Klicken auf die Kopfzeile die Sortierung nicht wie bei Online-Beispielen durch (es passiert überhaupt nichts). Ich versuche, diese Demo lokal zum Laufen
zu bringen:
https://material.angular.io/components/sort/overview https://plnkr.co/edit/XF5VxOSEBxMTd9Yb3ZLA?p=preview
Ich habe ein neues Projekt mit Angular CLI erstellt und dann die folgenden Schritte ausgeführt: https://material.angular.io/guide/getting-started
Hier sind meine lokalen Dateien:
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 */
Hat jemand eine Idee, warum es wie die Online-Tabelle angezeigt wird, aber die Sortierfunktion fehlt?
quelle
ng test --sm=false
und sehen Sie, was herauskommt.Antworten:
Für alle anderen, die dieses Problem haben könnten: Das Problem war, dass ich die API-Referenz auf der Website für eckige Materialien nicht richtig gelesen habe. Dieser Teil besagte, dass ich MatSortModule importieren musste. Nachdem ich meine Importliste in app.module.ts in geändert habe
es hat gut funktioniert
quelle
BrowserAnimationsModule
auch in app.module.tsMatSortModule
und importiert undBrowserAnimationsModule
sichergestellt, dass der matColumnDef-Wert mit dem Eigenschaftsnamen übereinstimmt, aber ich kann ihn immer noch nicht dazu bringen, etwas zu tun.Ich hatte ein Problem damit, dass die Sortierfunktion funktionierte, aber nicht richtig sortierte. Mir wurde klar, dass
matColumnDef
derselbe Name der Eigenschaft von mir sein mussclass / interface
, auf die ich mich beziehematCellDef
.Gemäß der Angular Material- Dokumentation :
Zum Beispiel:
Die
name
in dermatColumnDef
Direktive muss mit dername
in der<mat-cell>
Komponente verwendeten identisch sein .quelle
element
, wie diese `{{row.getName ()}}`Wenn sich die Tabelle in * ngIf befindet, funktioniert sie nicht. Es wird funktionieren, wenn es in [versteckt] geändert wird.
quelle
<div *ngIf="xxx">
der<div [hidden]="!xxx">
Der Name matColumnDef und der tatsächliche Wert * matCellDef sollten identisch sein
Beispiel:
In meinem Fall ist oppNo für matColumnDef name und * matCellDef name gleich und die Sortierung funktioniert einwandfrei.
quelle
Das Hinzufügen einer Sortierung innerhalb des Timeout-Blocks funktioniert für mich.
Wenn Sie keine Lifecykle-Haken verwenden möchten.
quelle
Ich habe auch dieses Problem getroffen. Da Sie auf die Definition des
AfterViewInit
untergeordneten Elements warten müssen, müssen Sie es implementieren und verwenden , nicht onInit.quelle
ngAfterViewInit
? Der Rest arbeitete vonngOnInit
. Es ist nur um zu versuchen zu verstehen, es ist dank dir behobenIch habe Stunden mit diesem Thema verbracht. Nachdem ich einige Themen durchgelesen habe, sind hier die Schritte, die ich ausgeführt habe.
MatSortModule
.*ngIf
. Ändern Sie ihn auf[hidden]
als @zerg empfohlen . (Ich verstehe nicht warum)Hoffe das hilft.
quelle
Meine Lösung bestand darin, mehrere Probleme zu beheben (im Grunde genommen wurden die meisten Lösungen auf dieser Seite zusammengeführt).
Dinge zu überprüfen:
BrowserModule, MatTableModule, MatSortModule
Module sollten in die Root-Modul-Datei importiert werden.MatTableDatasource
class verwendet haben, und übergeben Sie Ihr Datenarray als Parameter*ngIf=....
Direktive verschachtelt ist . Verwenden Sie stattdessen andere bedingte Operationen (verstehen Sie immer noch nicht warum).quelle
Für mich hat das Ersetzen von * ngIf durch das Attribut [hidden] für das Mat-Table-Tag funktioniert. Wie kann ich diesen als Fehler in der Angular Material-Community veröffentlichen?
quelle
Ich habe dies in meinem Szenario behoben, indem ich die Tabellendaten mit demselben Namen wie * matColumnDef benannt habe. Beispiel:
Stattdessen
quelle
Es gab 2 Probleme für mich.
Ich habe die Daten vom Dienst erhalten. Die Sortierung ngOnInit funktionierte nicht. Ersetzt mit
ngAfterViewInit () {this.dataSource.sort = this.sort; }}
quelle
Ich habe diesen alten Blog gefunden, der mir geholfen hat, ihn zum Laufen zu bringen: https://www.jeffryhouser.com/index.cfm/2018/10/23/Five-Reasons-My-ngMaterial-Table-wont-sort
MatSortModule
matSort
Header anMatTableDataSource
<table mat-table [dataSource]="this.products" matSort>
verwiesen ( ), aber ich hätte das Datenquellenobjekt verwenden sollen, das ich im Code (<table mat-table [dataSource]="this.dataSource" matSort>
) initialisiert habe . Die Datenquelle wird wie folgt initialisiertdataSource = new MatTableDataSource(this.products)
ngOnInit
/ mitngAfterViewInit
MatTableDataSource
quelle
Wenn sich Ihre Tabelle in einem * ngIf befindet und Sie der Meinung sind, dass dies damit zu tun hat, dass Ihre Tabelle nicht sortiert wird
sortingDataAccessor
, kann das Problem durch Angabe Ihrer eigenen Funktion wie bei mir behoben werden . Ich habe meine Tabelle in ein paar * ngIfs und es machte keinen Sinn, sie aus diesen * ngIfs herauszunehmen:quelle
Einer der Gründe, warum MatSort möglicherweise nicht funktioniert, besteht darin, dass es einer dataSource (dh
this.dataSource.sort = this.sort
) hinzugefügt wird, bevor es definiert wird. Dafür kann es mehrere Gründe geben:Wenn Sie die Sortierung in ngOnInit hinzufügen. Zu diesem Zeitpunkt ist die Vorlage noch nicht gerendert, sodass der MatSort, mit dem Sie arbeiten,
@ViewChild(MatSort, { static: true }) sort: MatSort;
undefiniert ist und verständlicherweise nichts tut. Eine Lösung für dieses Problem besteht darin,this.dataSource.sort = sort
zu ngAfterViewInit zu wechseln. Wenn ngAfterViewInit aufgerufen wird, wird Ihre Komponente gerendert und MatSort sollte definiert werden.Wenn Sie * ngIf verwenden, ist dies Ihre Vorlage für Ihr Tabellenelement oder eine, wenn es sich um übergeordnete Elemente handelt. * ngIf bewirkt, dass Ihre Tabelle in dem Moment, in dem Sie versuchen, MatSort festzulegen, nicht gerendert wird. Zum Beispiel, wenn Sie
*ngIf="dataSource.data.length > 0"
auf Ihrem Tabellenelement haben (um es nur zu rendern, wenn Daten vorhanden sind) und Siethis.dataSource.sort = this.sort
direkt nach dem Festlegenthis.dataSource.data
Ihrer Daten festlegen . Die Komponentenansicht wird noch nicht neu gerendert, sodass MatSort weiterhin undefiniert ist.Um MatSort zur Arbeit zu kommen und noch Ihren Tisch bedingt zeigen Sie könnten entscheiden , die zu ersetzen ,
*ngIf
mit[hidden]
wie in mehreren anderen Antworten angegeben. Wenn Sie jedoch Ihre * ngIf-Anweisung beibehalten möchten, können Sie die folgende Lösung verwenden. Diese Lösung funktioniert für Angular 9, ich habe sie in früheren Versionen nicht getestet, daher bin ich mir nicht sicher, ob sie dort funktioniert.Ich habe diese Lösung hier gefunden: https://github.com/angular/components/issues/10205
Anstatt zu setzen:
Verwenden Sie einen Setter für matSort. Dieser Setter wird ausgelöst, sobald sich matSort in Ihrer Ansicht ändert (dh beim ersten Mal definiert wird). Er wird nicht ausgelöst, wenn Sie Ihre Sortierung durch Klicken auf die Pfeile ändern. Das wird so aussehen:
Wenn Sie andere Funktionen haben, die die Sortierung (programmgesteuert) ändern, bin ich mir nicht sicher, ob sie erneut ausgelöst wird. Ich habe dies nicht getestet. Wenn Sie nicht sicherstellen möchten, dass die Sortierung nur festgelegt wird, wenn die Sortierung undefiniert war, können Sie Folgendes tun:
quelle
Überprüfen Sie, ob in der Konsole Javascript-Fehler vorliegen. Es kann sein, dass etwas anderes fehlgeschlagen ist, bevor Ihre Sortierung initialisiert wurde.
quelle