Staram się, aby mat-table
sortowanie działało lokalnie i chociaż mogę sprawić, by dane były wyświetlane zgodnie z oczekiwaniami, kliknięcie wiersza nagłówka nie powoduje sortowania, tak jak w przypadku przykładów online (w ogóle nic się nie dzieje). Próbuję, aby to demo działało lokalnie:
https://material.angular.io/components/sort/overview
https://plnkr.co/edit/XF5VxOSEBxMTd9Yb3ZLA?p=preview
Wygenerowałem nowy projekt za pomocą Angular CLI, a następnie wykonałem następujące kroki: https://material.angular.io/guide/getting-started
Oto moje pliki lokalne:
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 */
Czy ktoś ma pomysł, dlaczego miałby wyglądać jak tabela online, ale brakuje mu funkcji sortowania?
źródło
ng test --sm=false
i zobacz, co wyjdzie.Odpowiedzi:
Dla każdego, kto może mieć ten problem: Problem polegał na tym, że nie przeczytałem poprawnie referencji API na stronie materiałów kątowych, w części, która mówi, że muszę zaimportować MatSortModule. Po zmianie listy importów w app.module.ts na
działało dobrze
źródło
BrowserAnimationsModule
jest również importowany w app.module.tsMatSortModule
iBrowserAnimationsModule
i upewniłem się, że wartość matColumnDef jest zgodna z nazwą właściwości, ale nadal nie jestem w stanie nic zrobić.Miałem problem, że funkcja sortowania działa, ale nie sortowała prawidłowo. Zdałem sobie sprawę, że
matColumnDef
musi mieć taką samą nazwę właściwości mojejclass / interface
, w której się odwołujęmatCellDef
.Zgodnie z dokumentacją Angular Material :
Na przykład:
name
WmatColumnDef
dyrektywie musi być takie same jakname
używane w<mat-cell>
komponencie.źródło
element
, taką jak ten `{{row.getName ()}}`Jeśli tabela znajduje się wewnątrz * ngIf, nie będzie działać. Będzie działać, jeśli zostanie zmieniony na [ukryty]
źródło
<div *ngIf="xxx">
z<div [hidden]="!xxx">
Nazwa matColumnDef i rzeczywista nazwa wartości * matCellDef powinny być takie same
Przykład:
W moim przypadku oppNo jest takie samo dla nazwy matColumnDef i nazwy * matCellDef, a sortowanie działa poprawnie.
źródło
Dodanie sortowania w ramach limitu czasu działa dla mnie,
Jeśli nie chcesz używać haczyków lifecykle.
źródło
Trafiłem też w ten problem. Ponieważ musisz poczekać na zdefiniowanie dziecka, musisz implementować i używać
AfterViewInit
, a nie onInit.źródło
ngAfterViewInit
? Reszta pracowała odngOnInit
. To tylko próba zrozumienia, to naprawione dzięki tobieSpędziłem godziny nad tą kwestią. Po przeczytaniu kilku wątków, oto kroki, które zrobiłem.
MatSortModule
.*ngIf
. Zmień go[hidden]
jako @zerg zalecane . (Nie rozumiem dlaczego)Mam nadzieję że to pomoże.
źródło
Moim rozwiązaniem było naprawienie kilku rzeczy (w zasadzie scalenie większości rozwiązań na tej stronie).
Rzeczy do sprawdzenia:
BrowserModule, MatTableModule, MatSortModule
Moduły należy importować do głównego pliku modułów.MatTableDatasource
klasy i przekaż w niej swoją tablicę danych jako parametr*ngIf=....
dyrektywie. Zamiast tego użyj innych operacji warunkowych (nadal nie rozumiem, dlaczego).źródło
U mnie zastąpienie * ngIf atrybutem [hidden] dla tagu mat-table zadziałało. Jak opublikować ten jako błąd w społeczności Angular Material?
źródło
Naprawiłem to w moim scenariuszu, nazywając dane tabeli o tej samej nazwie co * matColumnDef Na przykład:
Zamiast
źródło
Były dla mnie 2 problemy.
Otrzymywałem dane z usługi. Sortowanie ngOnInit nie działało. Zastąpiony
ngAfterViewInit () {this.dataSource.sort = this.sort; }
źródło
Znalazłem starego bloga, który pomógł mi w uruchomieniu go: https://www.jeffryhouser.com/index.cfm/2018/10/23/Five-Reasons-My-ngMaterial-Table-wont-sort
MatSortModule
matSort
nagłówekMatTableDataSource
<table mat-table [dataSource]="this.products" matSort>
), ale powinienem był użyć obiektu źródła danych, który zainicjowałem w kodzie (<table mat-table [dataSource]="this.dataSource" matSort>
). Źródło danych jest inicjowane jakdataSource = new MatTableDataSource(this.products)
ngOnInit
/ngAfterViewInit
MatTableDataSource
źródło
Jeśli twoja tabela znajduje się wewnątrz * ngI i myślisz, że ma to coś wspólnego z tym, że nie sortuje twojej tabeli, określenie własnej
sortingDataAccessor
funkcji może rozwiązać problem, tak jak w przypadku mnie. Mam swój stół w kilku * ngIfs i wyjęcie go z tych * ngIfs nie miało sensu:źródło
Jednym z powodów, dla których MatSort może nie działać, jest dodanie go do źródła danych (tj.
this.dataSource.sort = this.sort
) Przed jego zdefiniowaniem. Przyczyn może być wiele:jeśli dodasz sortowanie w ngOnInit. W tym momencie szablon nie jest jeszcze renderowany, więc MatSort, który otrzymujesz,
@ViewChild(MatSort, { static: true }) sort: MatSort;
jest niezdefiniowany i zrozumiałe, że nic nie zrobi. Rozwiązaniem tego problemu jest przejściethis.dataSource.sort = sort
do ngAfterViewInit. Gdy wywoływana jest funkcja ngAfterViewInit, renderowany jest komponent i należy zdefiniować MatSort.kiedy używasz * ngIf jest twoim szablonem w elemencie tabeli lub takim, jeśli jest to element nadrzędny, a to * ngIf powoduje, że twoja tabela nie jest renderowana w momencie próby ustawienia MatSort. Na przykład, jeśli masz
*ngIf="dataSource.data.length > 0"
element tabeli (aby renderować go tylko wtedy, gdy są obecne dane) i ustawiłeśthis.dataSource.sort = this.sort
zaraz po ustawieniuthis.dataSource.data
z danymi. Widok komponentu nie zostanie jeszcze zrenderowany, więc MatSort nadal będzie niezdefiniowany.Aby uzyskać MatSort do pracy i nadal warunkowo pokazać swoją tabelę można zdecydować się wymienić
*ngIf
z[hidden]
jak stwierdzono w wielu innych odpowiedzi. Jeśli jednak chcesz zachować swoje oświadczenie * ngIf, możesz skorzystać z następującego rozwiązania. To rozwiązanie działa na Angular 9, nie testowałem go na poprzednich wersjach, więc nie jestem pewien, czy tam działa.Znalazłem to rozwiązanie tutaj: https://github.com/angular/components/issues/10205
Zamiast wstawiać:
użyj setera dla matSort. Ten seter uruchomi się, gdy matSort w twoim widoku zmieni się (tj. Zostanie zdefiniowany po raz pierwszy), nie zostanie uruchomiony, gdy zmienisz sortowanie, klikając strzałki. Będzie to wyglądać tak:
Jeśli masz inne funkcje, które (programowo) zmieniają sortowanie, nie jestem pewien, czy znowu się uruchomią, nie testowałem tego. Jeśli nie chcesz się upewnić, że ustawia sortowanie tylko wtedy, gdy sortowanie było niezdefiniowane, możesz zrobić coś takiego:
źródło
Sprawdź, czy masz jakieś błędy javascript w konsoli. Może się zdarzyć, że coś innego nie powiodło się przed zainicjowaniem sortowania.
źródło
Właściwie nazwa matColumnDef (tj. Nazwa kolumny) i nazwa właściwości klasy / interfejsu powinny być takie same, aby działało.
Czasami nie możemy zmienić nazwy naszej właściwości klasy / interfejsu, w takim przypadku możemy zaimplementować niestandardowe sortowanie, jak poniżej.
jeśli wykonamy sortowanie w kolumnie „id”, to nie zadziała. Spróbuj z niestandardowym sortowaniem
źródło