Home > Back-end >  Multiple Mat Paginator not working in Angular component
Multiple Mat Paginator not working in Angular component

Time:04-25

I've three different div (Post, Todo, User), based on user selection I display different table. For example, by default Post section loads with table of 100 records. If user selects Todo section, table should display Todo records and so on with pagination.

I've three datasource and three paginators in angular component. All these table data are fetched using REST GET call. I'm getting all the data but the pagination is not working as expected.

Pagination is working only for the Post section, remaining two (todo and user) paginators are not working.

Please find my code below, what I'm doing wrong here - I'm struggling from last two days not able to figure out why pagination is not working for all of them.

It would be really appreciated if you could help me with below issues. Appreciated your help in advance. Thanks!

Post has total 100 records

Todo has total 200 records

User has total 10 records

my-service.component.ts

import { Component, OnInit, ViewChild, ViewChildren, QueryList } from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations';
import { MatTableDataSource } from '@angular/material/table';
import { MatPaginator, PageEvent } from '@angular/material/paginator';
import { MatSort, Sort } from '@angular/material/sort';
import { MyService } from './my-service';
import { Todo } from './todos';
//import {MatAutocompleteTrigger} from '@angular/material/autocomplete';

@Component({
    selector: 'demo-service',
    templateUrl: './demo-service.component.html',
    styleUrls: ['./demo-service.component.scss'],
    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 DemoServiceComponent implements OnInit {
    selectedProject: string = 'Posts';

   

    postDataSource = new MatTableDataSource();
    postColumns = ['userId', 'title', 'body'];
    @ViewChild('postPaginator') postPaginator: MatPaginator;


    todoDataSource = new MatTableDataSource();
    toDoColumns = ['userId', 'title', 'completed'];
    @ViewChild('todoPaginator') todoPaginator: MatPaginator

    userDataSource = new MatTableDataSource();
    userColumns = ['id', 'name', 'username', 'email'];
    @ViewChild('userPaginator') userPaginator: MatPaginator


    ngAfterViewInit() {
        this.postDataSource.paginator = this.postPaginator;
        this.todoDataSource.paginator = this.todoPaginator;
        this.userDataSource.paginator = this.userPaginator;
        
    }

         

    /**
     * Constructor
     */
    constructor(
        private myService: MyService
    ) { }

    loadData() {
        this.onGetToDo();
        this.onGetPost();
        this.onGetUser();
    }

    onGetToDo(): void {
        this.myService.getTodo().subscribe(
            (response) => {
                this.todoDataSource.data = response;
            },
            (error: any) => {
            },
            () => console.log('Done getting all todos')
        );
    }

    onGetPost(): void {
        this.myService.getPost().subscribe(
            (response) => {
                this.postDataSource.data = response;
            },
            (error: any) => {
                console.log('entering into error block')
            },
            () => console.log('Done getting all posts')
        );
    }

    onGetUser(): void {
        this.myService.getUser().subscribe(
            (response) => {
                this.userDataSource.data = response;
            },
            (error: any) => {
                console.log('entering into error block')
            },
            () => console.log('Done getting all posts')
        );
    }


    ngOnInit(): void {
        this.loadData();
    }

    filterTodoData($event: any) {
        this.todoDataSource.filter = $event.target.value;
    }

    filterPostData($event: any) {
        this.todoDataSource.filter = $event.target.value;
    }
    /**
     * Track by function for ngFor loops
     *
     * @param index
     * @param item
     */
    trackByFn(index: number, item: any): any {
        return item.id || index;
    }

}

HTML File

<div >
    <div >
        <div >
            <div >
                <div >
                    <div >
                        <ng-container *transloco="let t">
                            <div
                                >
                                List Data</div>
                        </ng-container>
                    </div>
                </div>
            </div>
            <div 
                matRipple [matMenuTriggerFor]="projectsMenu">
                <div >
                    <div >
                        <div >{{selectedProject}}</div>
                    </div>
                    <div >
                        <mat-icon  [svgIcon]="'heroicons_solid:chevron-down'"></mat-icon>
                    </div>
                </div>
                <mat-menu #projectsMenu="matMenu" [xPosition]="'before'">
                    <button mat-menu-item (click)="selectedProject='Posts'">Posts
                    </button>
                    <button mat-menu-item (click)="selectedProject='Todo'">To Do
                    </button>

                    <button mat-menu-item (click)="selectedProject='User'">User
                    </button>
                </mat-menu>
            </div>
        </div>
    </div>

    <div  *ngIf="selectedProject === 'Posts'">
        <div  data-ng-init='listAllTopics()'>

            <mat-tab-group  [animationDuration]="'0'">
                <mat-tab label="Posts">
                    <ng-template matTabContent>

                        <div >
                            <div
                                >
                                <mat-form-field >
                                    <mat-icon  matPrefix [svgIcon]="'heroicons_solid:search'">
                                    </mat-icon>
                                    <input matInput (keyup)="filterPostData($event)" [autocomplete]="'off'"
                                        [placeholder]="'Search'">
                                </mat-form-field>
                                <div >

                                    <table  mat-table matSort
                                        (matSortChange)="announceSortChange($event)" [dataSource]="postDataSource"
                                        multiTemplateDataRows>

                                        <ng-container matColumnDef="userId">
                                            <th mat-header-cell *matHeaderCellDef mat-sort-header> userId </th>
                                            <td mat-cell *matCellDef="let element"> {{element.userId}} </td>
                                        </ng-container>


                                        <ng-container matColumnDef="title">
                                            <th mat-header-cell *matHeaderCellDef mat-sort-header> title </th>
                                            <td mat-cell *matCellDef="let element"> {{element.title}} </td>
                                        </ng-container>

                                        <ng-container matColumnDef="body">
                                            <th mat-header-cell *matHeaderCellDef mat-sort-header> body </th>
                                            <td mat-cell *matCellDef="let element"> {{element.body}} </td>
                                        </ng-container>

                                        <tr mat-header-row *matHeaderRowDef="postColumns;sticky: true"></tr>
                                        <tr mat-row *matRowDef="let element; columns: postColumns;"
                                            
                                            [class.student-expanded-row]="expandedElement === element"
                                            (click)="expandedElement = expandedElement === element ? null : element">
                                        </tr>

                                    </table>
                                    <mat-paginator #postPaginator="matPaginator"
                                        [length]="this.postDataSource?.filteredData?.length" [pageSize]="10"
                                        [pageSizeOptions]="[10, 20, 30, 50]" showFirstLastButtons>
                                    </mat-paginator>

                                </div>
                            </div>
                        </div>

                    </ng-template>

                </mat-tab>
            </mat-tab-group>
        </div>

    </div>

    <div  *ngIf="selectedProject === 'Todo'">
        <div  data-ng-init='listAllTopics()'>

            <mat-tab-group  [animationDuration]="'0'">
                <mat-tab label="Todos">
                    <ng-template matTabContent>

                        <div >
                            <div
                                >
                                <mat-form-field >
                                    <mat-icon  matPrefix [svgIcon]="'heroicons_solid:search'">
                                    </mat-icon>
                                    <input matInput (keyup)="filterTodoData($event)" [autocomplete]="'off'"
                                        [placeholder]="'Search'">
                                </mat-form-field>
                                <div >

                                    <table  mat-table matSort
                                        (matSortChange)="announceSortChange($event)" [dataSource]="todoDataSource"
                                        multiTemplateDataRows>

                                        <ng-container matColumnDef="userId">
                                            <th mat-header-cell *matHeaderCellDef mat-sort-header> userId </th>
                                            <td mat-cell *matCellDef="let element"> {{element.userId}} </td>
                                        </ng-container>


                                        <ng-container matColumnDef="title">
                                            <th mat-header-cell *matHeaderCellDef mat-sort-header> title </th>
                                            <td mat-cell *matCellDef="let element"> {{element.title}} </td>
                                        </ng-container>

                                        <ng-container matColumnDef="completed">
                                            <th mat-header-cell *matHeaderCellDef mat-sort-header> completed </th>
                                            <td mat-cell *matCellDef="let element"> {{element.completed}} </td>
                                        </ng-container>

                                        <tr mat-header-row *matHeaderRowDef="toDoColumns;sticky: true"></tr>
                                        <tr mat-row *matRowDef="let element; columns: toDoColumns;"
                                            
                                            [class.student-expanded-row]="expandedElement === element"
                                            (click)="expandedElement = expandedElement === element ? null : element">
                                        </tr>

                                    </table>

                                    <mat-paginator #todoPaginator="matPaginator"
                                        [length]="this.todoDataSource?.filteredData?.length" [pageSize]="10"
                                        [pageSizeOptions]="[10, 20, 30, 50]" showFirstLastButtons>
                                    </mat-paginator>

                                </div>
                            </div>
                        </div>

                    </ng-template>

                </mat-tab>
            </mat-tab-group>
        </div>
    </div>

    <div  *ngIf="selectedProject === 'User'">
        <div  data-ng-init='listAllTopics()'>

            <mat-tab-group  [animationDuration]="'0'">
                <mat-tab label="User">
                    <ng-template matTabContent>

                        <div >
                            <div
                                >
                                <mat-form-field >
                                    <mat-icon  matPrefix [svgIcon]="'heroicons_solid:search'">
                                    </mat-icon>
                                    <input matInput (keyup)="filterPostData($event)" [autocomplete]="'off'"
                                        [placeholder]="'Search'">
                                </mat-form-field>
                                <div >

                                    <table  mat-table matSort
                                        (matSortChange)="announceSortChange($event)" [dataSource]="userDataSource"
                                        multiTemplateDataRows>

                                        <ng-container matColumnDef="id">
                                            <th mat-header-cell *matHeaderCellDef mat-sort-header> id </th>
                                            <td mat-cell *matCellDef="let element"> {{element.id}} </td>
                                        </ng-container>


                                        <ng-container matColumnDef="name">
                                            <th mat-header-cell *matHeaderCellDef mat-sort-header> name </th>
                                            <td mat-cell *matCellDef="let element"> {{element.name}} </td>
                                        </ng-container>

                                        <ng-container matColumnDef="username">
                                            <th mat-header-cell *matHeaderCellDef mat-sort-header> username </th>
                                            <td mat-cell *matCellDef="let element"> {{element.username}} </td>
                                        </ng-container>

                                        <ng-container matColumnDef="email">
                                            <th mat-header-cell *matHeaderCellDef mat-sort-header> email </th>
                                            <td mat-cell *matCellDef="let element"> {{element.email}} </td>
                                        </ng-container>

                                        <tr mat-header-row *matHeaderRowDef="userColumns;sticky: true"></tr>
                                        <tr mat-row *matRowDef="let element; columns: userColumns;"
                                            
                                            [class.student-expanded-row]="expandedElement === element"
                                            (click)="expandedElement = expandedElement === element ? null : element">
                                        </tr>

                                    </table>

                                    <mat-paginator #userPaginator="matPaginator"
                                        [length]="this.userDataSource?.filteredData?.length" [pageSize]="5"
                                        [pageSizeOptions]="[5, 10, 30, 50]" showFirstLastButtons>
                                    </mat-paginator>

                                </div>
                            </div>
                        </div>

                    </ng-template>

                </mat-tab>
            </mat-tab-group>
        </div>

    </div>
</div>

Service class:

import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { Observable } from "rxjs";
import { Todo } from "./todos";
import { Post } from "./post";
import { User } from "./user";


@Injectable({ providedIn: 'root' })
export class MyService {

    constructor(private http: HttpClient) { }

    getTodo(): Observable<Todo[]> {
        return this.http.get<Todo[]>('http://jsonplaceholder.typicode.com/todos');
    }

    getPost(): Observable<Post[]> {
        return this.http.get<Post[]>('http://jsonplaceholder.typicode.com/posts');
    }    

    getUser(): Observable<User[]> {
        return this.http.get<User[]>('http://jsonplaceholder.typicode.com/users');
    }  
}

CodePudding user response:

Because you are using *ngIf, the rendered template does not have the elements todo and user when ngAfterViewInit is executed.

You can avoid it by modifying *ngif to [hidden] and reverse the conditions.

<div  [hidden]="selectedProject !== 'Posts'">
<div  [hidden]="selectedProject !== 'Todo'">
<div  [hidden]="selectedProject !== 'User'">
  • Related