Angular material table 使用 http.get() 时排序不起作用
Angular material table sort not working when using http.get()
在我尝试使用 angular material table 显示数据时,我发现当使用硬编码内联 json 时,我的 table 按预期排序。但是,当通过 http.get() 检索 json 时,排序不再有效。
为说明此问题而创建的示例服务:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class ApiService {
constructor(private http: HttpClient) {}
getDataHttp(): Observable<any> {
return this.http.get('assets/data.json');
}
getDataInline(): Observable<any> {
var data = [
. . .
];
return of(data);
}
}
和相应的 table 组件:
import { Component, Input, OnInit, ViewChild } from '@angular/core';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { ApiService } from '../../services/api.service';
@Component({
selector: 'app-table',
templateUrl: './table.component.html',
styleUrls: ['./table.component.css'],
})
export class TableComponent implements OnInit {
@Input() name: string = '';
displayedColumns = ['id', 'name', 'value'];
dataSource: MatTableDataSource<any>;
@ViewChild(MatSort) sort!: MatSort;
constructor(private api: ApiService) {
this.dataSource = new MatTableDataSource();
}
ngOnInit(): void {
if (this.name === 'Inline') {
this.api.getDataInline().subscribe((response) => {
this.dataSource = new MatTableDataSource(response);
});
} else if (this.name === 'Http') {
this.api.getDataHttp().subscribe((response) => {
this.dataSource = new MatTableDataSource(response);
});
}
}
ngAfterViewInit() {
this.dataSource.sort = this.sort;
}
}
和相应的视图:
<div>
<h5>{{ name }}</h5>
<table mat-table [dataSource]="dataSource" matSort>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Id</th>
<td mat-cell *matCellDef="let row">{{ row.id }}</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
<td mat-cell *matCellDef="let row">{{ row.name }}</td>
</ng-container>
<ng-container matColumnDef="value">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Value</th>
<td mat-cell *matCellDef="let row">{{ row.value }}</td>
</ng-container>
</table>
</div>
Stackblitz:https://stackblitz.com/edit/angular-ivy-qk3s2y
为什么排序对内联 table 有效,但对 http table 无效?
这个:
ngAfterViewInit() {
this.dataSource.sort = this.sort;
}
在 http 请求完成之前执行。我们需要记住这是异步的,所以你应该在收到数据后设置排序:
this.api.getDataHttp().subscribe((response) => {
this.dataSource = new MatTableDataSource(response);
this.dataSource.sort = this.sort; // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
});
在我尝试使用 angular material table 显示数据时,我发现当使用硬编码内联 json 时,我的 table 按预期排序。但是,当通过 http.get() 检索 json 时,排序不再有效。
为说明此问题而创建的示例服务:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class ApiService {
constructor(private http: HttpClient) {}
getDataHttp(): Observable<any> {
return this.http.get('assets/data.json');
}
getDataInline(): Observable<any> {
var data = [
. . .
];
return of(data);
}
}
和相应的 table 组件:
import { Component, Input, OnInit, ViewChild } from '@angular/core';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { ApiService } from '../../services/api.service';
@Component({
selector: 'app-table',
templateUrl: './table.component.html',
styleUrls: ['./table.component.css'],
})
export class TableComponent implements OnInit {
@Input() name: string = '';
displayedColumns = ['id', 'name', 'value'];
dataSource: MatTableDataSource<any>;
@ViewChild(MatSort) sort!: MatSort;
constructor(private api: ApiService) {
this.dataSource = new MatTableDataSource();
}
ngOnInit(): void {
if (this.name === 'Inline') {
this.api.getDataInline().subscribe((response) => {
this.dataSource = new MatTableDataSource(response);
});
} else if (this.name === 'Http') {
this.api.getDataHttp().subscribe((response) => {
this.dataSource = new MatTableDataSource(response);
});
}
}
ngAfterViewInit() {
this.dataSource.sort = this.sort;
}
}
和相应的视图:
<div>
<h5>{{ name }}</h5>
<table mat-table [dataSource]="dataSource" matSort>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Id</th>
<td mat-cell *matCellDef="let row">{{ row.id }}</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
<td mat-cell *matCellDef="let row">{{ row.name }}</td>
</ng-container>
<ng-container matColumnDef="value">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Value</th>
<td mat-cell *matCellDef="let row">{{ row.value }}</td>
</ng-container>
</table>
</div>
Stackblitz:https://stackblitz.com/edit/angular-ivy-qk3s2y
为什么排序对内联 table 有效,但对 http table 无效?
这个:
ngAfterViewInit() {
this.dataSource.sort = this.sort;
}
在 http 请求完成之前执行。我们需要记住这是异步的,所以你应该在收到数据后设置排序:
this.api.getDataHttp().subscribe((response) => {
this.dataSource = new MatTableDataSource(response);
this.dataSource.sort = this.sort; // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
});