无法向我的 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>

提前致谢

问题是您必须将 总可用数据长度 设置为 paginatorpageSize 参数。

例如,您有 30 个国家的数据,您的 pageSize10。因此,您必须将 paginatorpageSize 参数设置为 30,您的可见数据将为 10

我用静态数据嘲笑了你的AppService。并展示了如何为分页填充数据。

并且您还错过了 pageSizepage 更改后的过滤数据。我也做过。

看demo就明白了。

工作解决方案创建于 Stackblitz

你的Api端好像不支持数据分页。即使您在查询字符串中使用 pageSizepageNumber 参数请求,它也是 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.