Saya mencoba membuat mat-table
penyortiran berfungsi secara lokal, dan sementara saya bisa mendapatkan data untuk muncul seperti yang diharapkan, mengklik baris tajuk tidak melakukan penyortiran seperti pada contoh online (tidak ada yang terjadi sama sekali). Saya mencoba membuat demo ini bekerja secara lokal:
https://material.angular.io/components/sort/overview
https://plnkr.co/edit/XF5VxOSEBxMTd9Yb3ZLA?p=preview
Saya telah membuat proyek baru dengan Angular CLI, lalu mengikuti langkah-langkah berikut: https://material.angular.io/guide/getting-started
Ini file lokal saya:
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 */
Adakah yang tahu mengapa itu akan muncul seperti tabel online tetapi tidak memiliki fungsi penyortiran?
sumber
ng test --sm=false
dan lihat apa yang keluar.Jawaban:
Untuk siapa pun yang mungkin memiliki masalah ini: Masalahnya adalah saya tidak membaca referensi API dengan benar di situs web bahan sudut, bagian yang mengatakan saya harus mengimpor MatSortModule. Setelah saya mengubah daftar impor saya di app.module.ts menjadi
itu bekerja dengan baik
sumber
BrowserAnimationsModule
juga diimpor di app.module.tsMatSortModule
danBrowserAnimationsModule
, dan saya telah memastikan bahwa nilai matColumnDef cocok dengan nama properti, namun saya masih tidak dapat membuatnya melakukan apa pun.Saya mengalami masalah karena fungsi pengurutan berfungsi tetapi tidak dapat menyortir dengan benar. Saya menyadari bahwa
matColumnDef
harus memiliki nama yang sama dari properti sayaclass / interface
yang saya rujukmatCellDef
.Menurut dokumentasi Angular Material :
Sebagai contoh:
The
name
dalammatColumnDef
direktif harus sama denganname
yang digunakan dalam<mat-cell>
komponen.sumber
element
, seperti ini `{{row.getName ()}}`Jika tabel berada di dalam * ngIf, itu tidak akan berfungsi. Ini akan berfungsi jika diubah menjadi [tersembunyi]
sumber
<div *ngIf="xxx">
yang<div [hidden]="!xxx">
nama matColumnDef dan * nama nilai aktual matCellDef harus sama
Contoh:
Dalam kasus saya oppNo sama untuk nama matColumnDef dan * nama matCellDef dan penyortiran berfungsi dengan baik.
sumber
Menambahkan urutan dalam blok batas waktu berfungsi untuk saya,
Jika Anda tidak ingin menggunakan kait penyelamat.
sumber
Saya juga mengalami masalah ini. Karena Anda perlu menunggu turunannya ditentukan, Anda harus mengimplementasikan dan menggunakan
AfterViewInit
, bukan onInit.sumber
ngAfterViewInit
? Sisanya bekerja daringOnInit
. Ini hanya untuk mencoba memahami, itu diperbaiki berkat AndaSaya menghabiskan berjam-jam untuk masalah ini. Setelah membaca sejumlah utas, berikut adalah langkah-langkah yang saya lakukan.
MatSortModule
.*ngIf
. Ubah menjadi[hidden]
seperti yang direkomendasikan @zerg . (Saya tidak mengerti mengapa)Semoga ini membantu.
sumber
Solusi saya adalah memperbaiki beberapa hal (pada dasarnya menggabungkan sebagian besar solusi di halaman ini).
Hal-hal yang perlu diperiksa:
BrowserModule, MatTableModule, MatSortModule
Modul harus diimpor di file modul root.MatTableDatasource
kelas dan meneruskan larik data Anda di dalamnya sebagai parameter*ngIf=....
direktif. Gunakan operasi bersyarat lain sebagai gantinya (masih belum mengerti mengapa).sumber
Bagi saya, mengganti * ngIf dengan atribut [tersembunyi] untuk tag mat-table berfungsi. Bagaimana cara memposting ini sebagai bug ke komunitas Angular Material?
sumber
Saya memperbaiki ini dalam skenario saya dengan menamai data tabel dengan nama yang sama dengan * matColumnDef Misalnya:
Sebagai gantinya
sumber
Ada 2 masalah bagi saya.
Saya mendapatkan data dari layanan. Jenis ngOnInit tidak berfungsi. Digantikan dengan
ngAfterViewInit () {this.dataSource.sort = this.sort; }
sumber
Saya menemukan blog lama ini yang membantu saya membuatnya berfungsi: https://www.jeffryhouser.com/index.cfm/2018/10/23/Five-Reasons-My-ngMaterial-Table-wont-sort
MatSortModule
matSort
tajukMatTableDataSource
<table mat-table [dataSource]="this.products" matSort>
) tetapi saya seharusnya menggunakan objek sumber data yang saya inisialisasi di code (<table mat-table [dataSource]="this.dataSource" matSort>
). Sumber data diinisialisasi sepertidataSource = new MatTableDataSource(this.products)
ngOnInit
/ngAfterViewInit
MatTableDataSource
sumber
Jika tabel Anda berada di dalam * ngIf dan menurut Anda ada hubungannya dengan tidak mengurutkan tabel Anda, maka menentukan
sortingDataAccessor
fungsi Anda sendiri mungkin menyelesaikan masalah seperti yang terjadi pada saya. Saya memiliki tabel saya di dalam beberapa * ngIfs dan mengeluarkannya dari * ngIfs itu tidak masuk akal:sumber
Salah satu alasan MatSort mungkin tidak berfungsi, adalah ketika itu ditambahkan ke dataSource (yaitu
this.dataSource.sort = this.sort
) sebelum didefinisikan. Ada beberapa alasan untuk ini:jika Anda menambahkan jenis di ngOnInit. Pada titik ini template belum dirender, jadi MatSort yang Anda dapatkan
@ViewChild(MatSort, { static: true }) sort: MatSort;
belum ditentukan dan dapat dimengerti tidak akan melakukan apa pun. Solusi untuk masalah ini adalah berpindahthis.dataSource.sort = sort
ke ngAfterViewInit. Saat ngAfterViewInit dipanggil, komponen Anda dirender, dan MatSort harus ditentukan.ketika Anda menggunakan * ngIf adalah template Anda pada elemen tabel Anda atau satu jika itu elemen induk dan ini * ngIf menyebabkan tabel Anda tidak dirender pada saat Anda mencoba menyetel MatSort. Misalnya, jika Anda memiliki
*ngIf="dataSource.data.length > 0"
elemen tabel Anda (untuk hanya merendernya jika ada data yang ada) dan Anda menetapkanthis.dataSource.sort = this.sort
tepat setelah Anda menyetelthis.dataSource.data
dengan data Anda. Tampilan komponen belum dirender, jadi MatSort masih belum ditentukan.Agar MatSort berfungsi dan tetap menampilkan tabel secara bersyarat, Anda dapat memutuskan untuk menggantinya
*ngIf
dengan[hidden]
seperti yang dinyatakan dalam beberapa jawaban lainnya. Namun, jika Anda ingin menyimpan pernyataan * ngIf, Anda dapat menggunakan solusi berikut. Solusi ini berfungsi untuk Angular 9, saya belum mengujinya pada versi sebelumnya jadi saya tidak yakin apakah itu berfungsi di sana.Saya menemukan solusi ini di sini: https://github.com/angular/components/issues/10205
Alih-alih menempatkan:
gunakan penyetel untuk matSort. Penyetel ini akan aktif setelah matSort dalam tampilan Anda berubah (yaitu ditentukan pertama kali), penyetel ini tidak akan aktif saat Anda mengubah penyortiran dengan mengklik panah. Ini akan terlihat seperti ini:
Jika Anda memiliki fungsi lain yang (secara terprogram) mengubah pengurutan, saya tidak yakin apakah akan diaktifkan lagi, saya belum mengujinya. Jika Anda tidak ingin memastikan itu hanya menyetel pengurutan jika pengurutannya tidak ditentukan, Anda dapat melakukan sesuatu seperti ini:
sumber
Sebenarnya nama matColumnDef (yaitu nama kolom) dan nama properti Kelas / Antarmuka Anda harus sama agar dapat berfungsi.
Terkadang kami tidak dapat mengubah nama properti Kelas / Antarmuka kami, dalam hal ini, kami dapat menerapkan pengurutan khusus seperti di bawah ini.
jika kita melakukan penyortiran pada kolom 'id' itu tidak akan berhasil. Coba dengan penyortiran khusus
sumber
Bagi siapa pun yang bingung tentang penamaan ini harus sama, saya melakukan beberapa pengujian:
Ini akan berfungsi (nama properti sama dengan kolom def):
Ini TIDAK akan berfungsi (nama properti tidak sama dengan kolom def):
Fyi, ini juga TIDAK berfungsi (panjang properti):
Dan ini juga tidak:
sumber
Lihat apakah Anda memiliki kesalahan javascript di konsol. Bisa jadi ada hal lain yang gagal sebelum penyortiran Anda diinisialisasi.
sumber