'Multiple Mat Paginator not working in Angular component

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 class="flex flex-col flex-auto min-w-0">
    <div class="bg-card">
        <div class="flex flex-col w-full max-w-screen-xl mx-auto px-6 sm:px-8">
            <div class="flex flex-col sm:flex-row flex-auto sm:items-center min-w-0 my-8 sm:my-12">
                <div class="flex flex-auto items-center min-w-0">
                    <div class="flex flex-col min-w-0 ml-4">
                        <ng-container *transloco="let t">
                            <div
                                class="text-2xl md:text-5xl font-semibold tracking-tight leading-7 md:leading-snug truncate">
                                List Data</div>
                        </ng-container>
                    </div>
                </div>
            </div>
            <div class="relative flex self-start pt-2 pb-1 pl-5 pr-4 cursor-pointer overflow-hidden rounded-t-xl border border-b-0 bg-default"
                matRipple [matMenuTriggerFor]="projectsMenu">
                <div class="flex items-center">
                    <div class="overflow-hidden">
                        <div class="font-medium leading-6 truncate">{{selectedProject}}</div>
                    </div>
                    <div class="flex items-center justify-center pl-2">
                        <mat-icon class="icon-size-5" [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 class="flex-auto border-t -mt-px pt-4 sm:pt-6" *ngIf="selectedProject === 'Posts'">
        <div class="w-full max-w-screen-xl mx-auto" data-ng-init='listAllTopics()'>

            <mat-tab-group class="sm:px-2" [animationDuration]="'0'">
                <mat-tab label="Posts">
                    <ng-template matTabContent>

                        <div class="flex flex-wrap -mx-4">
                            <div
                                class="sm:col-span-6 flex flex-col flex-auto p-6 bg-card shadow rounded-2xl overflow-hidden">
                                <mat-form-field class="reduce-width">
                                    <mat-icon class="icon-size-5" matPrefix [svgIcon]="'heroicons_solid:search'">
                                    </mat-icon>
                                    <input matInput (keyup)="filterPostData($event)" [autocomplete]="'off'"
                                        [placeholder]="'Search'">
                                </mat-form-field>
                                <div class="flex flex-col flex-auto mt-2 overflow-x-auto">

                                    <table class="w-full bg-transparent" 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-element-row"
                                            [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 class="flex-auto border-t -mt-px pt-4 sm:pt-6" *ngIf="selectedProject === 'Todo'">
        <div class="w-full max-w-screen-xl mx-auto" data-ng-init='listAllTopics()'>

            <mat-tab-group class="sm:px-2" [animationDuration]="'0'">
                <mat-tab label="Todos">
                    <ng-template matTabContent>

                        <div class="flex flex-wrap -mx-4">
                            <div
                                class="sm:col-span-6 flex flex-col flex-auto p-6 bg-card shadow rounded-2xl overflow-hidden">
                                <mat-form-field class="reduce-width">
                                    <mat-icon class="icon-size-5" matPrefix [svgIcon]="'heroicons_solid:search'">
                                    </mat-icon>
                                    <input matInput (keyup)="filterTodoData($event)" [autocomplete]="'off'"
                                        [placeholder]="'Search'">
                                </mat-form-field>
                                <div class="flex flex-col flex-auto mt-2 overflow-x-auto">

                                    <table class="w-full bg-transparent" 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-element-row"
                                            [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 class="flex-auto border-t -mt-px pt-4 sm:pt-6" *ngIf="selectedProject === 'User'">
        <div class="w-full max-w-screen-xl mx-auto" data-ng-init='listAllTopics()'>

            <mat-tab-group class="sm:px-2" [animationDuration]="'0'">
                <mat-tab label="User">
                    <ng-template matTabContent>

                        <div class="flex flex-wrap -mx-4">
                            <div
                                class="sm:col-span-6 flex flex-col flex-auto p-6 bg-card shadow rounded-2xl overflow-hidden">
                                <mat-form-field class="reduce-width">
                                    <mat-icon class="icon-size-5" matPrefix [svgIcon]="'heroicons_solid:search'">
                                    </mat-icon>
                                    <input matInput (keyup)="filterPostData($event)" [autocomplete]="'off'"
                                        [placeholder]="'Search'">
                                </mat-form-field>
                                <div class="flex flex-col flex-auto mt-2 overflow-x-auto">

                                    <table class="w-full bg-transparent" 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-element-row"
                                            [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');
    }  
}


Solution 1:[1]

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 class="flex-auto border-t -mt-px pt-4 sm:pt-6" [hidden]="selectedProject !== 'Posts'">
<div class="flex-auto border-t -mt-px pt-4 sm:pt-6" [hidden]="selectedProject !== 'Todo'">
<div class="flex-auto border-t -mt-px pt-4 sm:pt-6" [hidden]="selectedProject !== 'User'">

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 N.F.