无法向我的 angular 项目添加分页
Cannot add pagination to my angular project
我已经尝试了所有我知道的事情,但没有成功。我想为 covid-19 添加分页 table。分页器显示 table 中有多少行,但不会将它们分成几页。
这是我完成的代码。
这是我的 component.ts
:
import { AfterViewInit, Component, HostListener, OnInit, ViewChild, } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTable } from '@angular/material/table';
import { merge } from 'rxjs';
import { tap } from 'rxjs/operators';
import { Countries, sortData } from '../app.model';
import { AppService } from '../app.service';
import { DataTableDataSource } from './data-table-datasource';
import { animate, state, style, transition, trigger, } from '@angular/animations';
@Component({
selector: 'app-data-table',
templateUrl: './data-table.component.html',
styleUrls: ['./data-table.component.css'],
animations: [
trigger('detailExpand', [
state('collapsed', style({ height: '0px', minHeight: '0' })),
state('expanded', style({ height: '*' })),
transition(
'expanded <=> collapsed',
animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')
),
]),
],
})
export class DataTableComponent implements AfterViewInit {
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort) sort!: MatSort;
@ViewChild(MatTable) table!: MatTable<Countries>;
@ViewChild('paginator', { read: MatPaginator }) paginatorlist: MatPaginator;
dataSource: DataTableDataSource;
filter: sortData = new sortData();
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = [];
scrWidth: any;
constructor(public appService: AppService) { }
ngOnInit() {
this.dataSource = new DataTableDataSource(this.appService);
this.sortData(false);
this.setupTable();
this.getScreenSize();
}
sortData(isChange: boolean) {
if (isChange) {
this.filter.pageSize = this.paginator.pageSize;
this.filter.pageNumber = this.paginator.pageIndex + 1;
// this.filter.sortColumn = this.sort.active;
// this.filter.sortDirection = this.sort.direction;
console.log(this.paginator.pageIndex);
} else {
this.filter.pageSize = 15;
this.filter.pageNumber = 1;
// this.filter.sortColumn = 'todayCases';
// this.filter.sortDirection = 'true';
// console.log(this.filter);
}
this.dataSource.loadData(this.filter);
(error) => console.error(error);
}
ngAfterViewInit() {
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
}
这是我的 datasource.ts
:
import { DataSource } from '@angular/cdk/collections';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { finalize, map } from 'rxjs/operators';
import { Observable, of as observableOf, merge, BehaviorSubject } from 'rxjs';
import { ApiResponse, Countries, sortData } from '../app.model';
import { AppService } from '../app.service';
export class DataTableDataSource extends DataSource<Countries> {
public dataSubject = new BehaviorSubject<Countries[]>([]);
private loadingSubject = new BehaviorSubject<boolean>(false);
public loading$ = this.loadingSubject.asObservable();
private totalDataCountSubject = new BehaviorSubject<number>(0);
public totalDataCount$ = this.totalDataCountSubject.asObservable();
paginator: MatPaginator;
sort: MatSort;
constructor(private appService: AppService) {
super();
}
loadData(filter: sortData) {
this.appService
.getData(filter)
.pipe(finalize(() => this.loadingSubject.next(false)))
.subscribe((data: any) => {
// console.log(data.response);
if (data) {
this.totalDataCountSubject.next(data.length);
this.dataSubject.next(data);
console.log(data.length);
}
});
}
connect(): Observable<Countries[]> {
return this.dataSubject.asObservable();
}
disconnect(): void {
this.dataSubject.complete();
this.totalDataCountSubject.complete();
this.loadingSubject.complete();
}
}
这是我的 HTML
:
<div class="mat-elevation-z8 data-table">
<table mat-table multiTemplateDataRows class="full-width-table" matSort matSortActive="todayCases" matSortDirection="asc"
aria-label="Elements" [dataSource]="dataSource">
<!-- Country Column -->
<ng-container matColumnDef="country">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Country</th>
<td mat-cell *matCellDef="let row">{{ row.country }}</td>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="cases">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Cases</th>
<td mat-cell *matCellDef="let row">{{ row.cases }}</td>
</ng-container>
<!-- Id Column -->
<ng-container matColumnDef="active">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Active</th>
<td mat-cell *matCellDef="let row">{{ row.active }}</td>
</ng-container>
<!-- Id Column -->
<ng-container matColumnDef="todayCases">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Today Cases</th>
<td mat-cell *matCellDef="let row">{{ row.todayCases }}</td>
</ng-container>
<!-- Id Column -->
<ng-container matColumnDef="todayDeaths">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Total Deaths</th>
<td mat-cell *matCellDef="let row">{{ row.todayDeaths }}</td>
</ng-container>
<!-- Id Column -->
<ng-container class="recovered" matColumnDef="recovered">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Recovered</th>
<td mat-cell *matCellDef="let row">{{ row.recovered }}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
<mat-paginator #paginator [length]="dataSource.totalDataCount$ | async" [pageSize]="15" [pageSizeOptions]="[15, 20, 25]">
</mat-paginator>
</div>
提前致谢
问题是您必须将 总可用数据长度 设置为 paginator
的 pageSize
参数。
例如,您有 30 个国家的数据,您的 pageSize
是 10。因此,您必须将 paginator
的 pageSize
参数设置为 30,您的可见数据将为 10。
我用静态数据嘲笑了你的AppService
。并展示了如何为分页填充数据。
并且您还错过了 pageSize
或 page
更改后的过滤数据。我也做过。
看demo就明白了。
工作解决方案创建于 Stackblitz
你的Api端好像不支持数据分页。即使您在查询字符串中使用 pageSize
和 pageNumber
参数请求,它也是 returns 所有数据。
解决办法是在客户端分页数据。您当前使用的数据源类型 (DataSource<T>
) 将增加客户端数据分页方案的复杂性。您应该使用 MatTableDataSource<T>
作为数据源 - 一旦您向它提供所有数据,它就会支持自动数据分页。
以下是您可以尝试的 StackBlitz 的 modified/simplified 版本 -
组件代码-
export class GalleryComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort) sort!: MatSort;
dataSource = new MatTableDataSource<Countries[]>([]);
displayedColumns = ['country', 'cases', 'active', 'todayDeaths', 'recovered'];
filter: sortData = new sortData();
constructor(public appService: AppService) { }
ngOnInit() {
this.loadData();
}
loadData() {
this.filter.sortColumn = 'country';
this.filter.sortDirection = 'asc';
this.appService.getData(this.filter).subscribe(
p => {
this.dataSource.data = p;
},
e => {
console.log(e);
});
}
ngAfterViewInit() {
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
}
在模板代码中,仅从 mat-paginator
-
中删除 length
绑定
<mat-paginator [pageSize]="15" [pageSizeOptions]="[15, 20, 25]"> </mat-paginator>
这应该足以使您的分页正常工作。您不需要使用 DataTableDataSource
.
我已经尝试了所有我知道的事情,但没有成功。我想为 covid-19 添加分页 table。分页器显示 table 中有多少行,但不会将它们分成几页。
这是我完成的代码。
这是我的 component.ts
:
import { AfterViewInit, Component, HostListener, OnInit, ViewChild, } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTable } from '@angular/material/table';
import { merge } from 'rxjs';
import { tap } from 'rxjs/operators';
import { Countries, sortData } from '../app.model';
import { AppService } from '../app.service';
import { DataTableDataSource } from './data-table-datasource';
import { animate, state, style, transition, trigger, } from '@angular/animations';
@Component({
selector: 'app-data-table',
templateUrl: './data-table.component.html',
styleUrls: ['./data-table.component.css'],
animations: [
trigger('detailExpand', [
state('collapsed', style({ height: '0px', minHeight: '0' })),
state('expanded', style({ height: '*' })),
transition(
'expanded <=> collapsed',
animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')
),
]),
],
})
export class DataTableComponent implements AfterViewInit {
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort) sort!: MatSort;
@ViewChild(MatTable) table!: MatTable<Countries>;
@ViewChild('paginator', { read: MatPaginator }) paginatorlist: MatPaginator;
dataSource: DataTableDataSource;
filter: sortData = new sortData();
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = [];
scrWidth: any;
constructor(public appService: AppService) { }
ngOnInit() {
this.dataSource = new DataTableDataSource(this.appService);
this.sortData(false);
this.setupTable();
this.getScreenSize();
}
sortData(isChange: boolean) {
if (isChange) {
this.filter.pageSize = this.paginator.pageSize;
this.filter.pageNumber = this.paginator.pageIndex + 1;
// this.filter.sortColumn = this.sort.active;
// this.filter.sortDirection = this.sort.direction;
console.log(this.paginator.pageIndex);
} else {
this.filter.pageSize = 15;
this.filter.pageNumber = 1;
// this.filter.sortColumn = 'todayCases';
// this.filter.sortDirection = 'true';
// console.log(this.filter);
}
this.dataSource.loadData(this.filter);
(error) => console.error(error);
}
ngAfterViewInit() {
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
}
这是我的 datasource.ts
:
import { DataSource } from '@angular/cdk/collections';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { finalize, map } from 'rxjs/operators';
import { Observable, of as observableOf, merge, BehaviorSubject } from 'rxjs';
import { ApiResponse, Countries, sortData } from '../app.model';
import { AppService } from '../app.service';
export class DataTableDataSource extends DataSource<Countries> {
public dataSubject = new BehaviorSubject<Countries[]>([]);
private loadingSubject = new BehaviorSubject<boolean>(false);
public loading$ = this.loadingSubject.asObservable();
private totalDataCountSubject = new BehaviorSubject<number>(0);
public totalDataCount$ = this.totalDataCountSubject.asObservable();
paginator: MatPaginator;
sort: MatSort;
constructor(private appService: AppService) {
super();
}
loadData(filter: sortData) {
this.appService
.getData(filter)
.pipe(finalize(() => this.loadingSubject.next(false)))
.subscribe((data: any) => {
// console.log(data.response);
if (data) {
this.totalDataCountSubject.next(data.length);
this.dataSubject.next(data);
console.log(data.length);
}
});
}
connect(): Observable<Countries[]> {
return this.dataSubject.asObservable();
}
disconnect(): void {
this.dataSubject.complete();
this.totalDataCountSubject.complete();
this.loadingSubject.complete();
}
}
这是我的 HTML
:
<div class="mat-elevation-z8 data-table">
<table mat-table multiTemplateDataRows class="full-width-table" matSort matSortActive="todayCases" matSortDirection="asc"
aria-label="Elements" [dataSource]="dataSource">
<!-- Country Column -->
<ng-container matColumnDef="country">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Country</th>
<td mat-cell *matCellDef="let row">{{ row.country }}</td>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="cases">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Cases</th>
<td mat-cell *matCellDef="let row">{{ row.cases }}</td>
</ng-container>
<!-- Id Column -->
<ng-container matColumnDef="active">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Active</th>
<td mat-cell *matCellDef="let row">{{ row.active }}</td>
</ng-container>
<!-- Id Column -->
<ng-container matColumnDef="todayCases">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Today Cases</th>
<td mat-cell *matCellDef="let row">{{ row.todayCases }}</td>
</ng-container>
<!-- Id Column -->
<ng-container matColumnDef="todayDeaths">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Total Deaths</th>
<td mat-cell *matCellDef="let row">{{ row.todayDeaths }}</td>
</ng-container>
<!-- Id Column -->
<ng-container class="recovered" matColumnDef="recovered">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Recovered</th>
<td mat-cell *matCellDef="let row">{{ row.recovered }}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
<mat-paginator #paginator [length]="dataSource.totalDataCount$ | async" [pageSize]="15" [pageSizeOptions]="[15, 20, 25]">
</mat-paginator>
</div>
提前致谢
问题是您必须将 总可用数据长度 设置为 paginator
的 pageSize
参数。
例如,您有 30 个国家的数据,您的 pageSize
是 10。因此,您必须将 paginator
的 pageSize
参数设置为 30,您的可见数据将为 10。
我用静态数据嘲笑了你的AppService
。并展示了如何为分页填充数据。
并且您还错过了 pageSize
或 page
更改后的过滤数据。我也做过。
看demo就明白了。
工作解决方案创建于 Stackblitz
你的Api端好像不支持数据分页。即使您在查询字符串中使用 pageSize
和 pageNumber
参数请求,它也是 returns 所有数据。
解决办法是在客户端分页数据。您当前使用的数据源类型 (DataSource<T>
) 将增加客户端数据分页方案的复杂性。您应该使用 MatTableDataSource<T>
作为数据源 - 一旦您向它提供所有数据,它就会支持自动数据分页。
以下是您可以尝试的 StackBlitz 的 modified/simplified 版本 -
组件代码-
export class GalleryComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
@ViewChild(MatSort) sort!: MatSort;
dataSource = new MatTableDataSource<Countries[]>([]);
displayedColumns = ['country', 'cases', 'active', 'todayDeaths', 'recovered'];
filter: sortData = new sortData();
constructor(public appService: AppService) { }
ngOnInit() {
this.loadData();
}
loadData() {
this.filter.sortColumn = 'country';
this.filter.sortDirection = 'asc';
this.appService.getData(this.filter).subscribe(
p => {
this.dataSource.data = p;
},
e => {
console.log(e);
});
}
ngAfterViewInit() {
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
}
在模板代码中,仅从 mat-paginator
-
length
绑定
<mat-paginator [pageSize]="15" [pageSizeOptions]="[15, 20, 25]"> </mat-paginator>
这应该足以使您的分页正常工作。您不需要使用 DataTableDataSource
.