Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot add pagination to my angular project

I have tried all the things I know but with no success. I want to add pagination to a covid-19 table. The paginator shows how much rows are in the table but it is not splitting them into pages.

Here is the code I've done.

Here is my 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;
    }
}

Here is my 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();
    }
}

And here is my 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>

Thanks in advance

like image 544
sutin Avatar asked Sep 10 '26 00:09

sutin


1 Answers

The issue is you have to set the total available data length to the pageSize parameter of the paginator.

For example, you have 30 countries' data and your pageSize is 10. So, you have to set the pageSize parameter of the paginator to 30 and your visible data will be 10.

I've mocked your AppService with static data. And showed how to populate data for pagination.

And you also missed filtering data after change of pageSize or page. I've also done that.

Observe the demo and you'll be able to understand.

Working solution created at Stackblitz

like image 198
Zunayed Shahriar Avatar answered Sep 11 '26 19:09

Zunayed Shahriar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!