Mat Paginator not working with *ngIf in angular

Viewed 46

I want to display the table based on the user selection, for example if user selects Posts - it should display table with all Post content. Likewise, if user selects Todo - it should display Todo table and so on. I created different datasource and I've different paginator for each datasource. But pagination is not working as expected.

Post has total 100 records

Todo has total 200 records

User has total 10 records

By default Post section loads and it shows table has 1-10 of 100 with proper pagination. When I switch from Post to Todo section - table shows only 1-10 of 10 but Todo has total 200 records - not sure why its overriding User datasource number of records in post and todo datasource. When I switch again from Todo to Post section, here also I see 1-10 of 10 instead 1-10 of 100 and pagination navigation not working.

Please find my code below - could you please help why User datasource overriding when conditional div switch happens?

Appreciated your help in advance. Thanks!

I'm using Angular: 13.2.5

demo-service.component.ts

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


@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';
    todoDataSource = new MatTableDataSource();
    toDoColumns = ['userId', 'title', 'completed'];

    postDataSource = new MatTableDataSource();
    postColumns = ['userId', 'title', 'body'];


    userDataSource = new MatTableDataSource();
    userColumns = ['id', 'name', 'username', 'email'];

    private postPaginator: MatPaginator;
    private postSort: MatSort;

    @ViewChild(MatSort, { static: false }) set postmatSort(ms: MatSort) {
        this.postSort = ms;
        this.setPostDataSourceAttributes();
    }

    @ViewChild(MatPaginator, { static: false }) set postmatPaginator(mp: MatPaginator) {
        this.postPaginator = mp;
        this.setPostDataSourceAttributes();
    }

    setPostDataSourceAttributes() {
        this.postDataSource.paginator = this.postPaginator;
        this.postDataSource.sort = this.postSort;
    }

    private todoPaginator: MatPaginator;
    private todoSort: MatSort;

    @ViewChild(MatSort, { static: false }) set matSort(ms: MatSort) {
        this.todoSort = ms;
        this.setTodoDataSourceAttributes();
    }

    @ViewChild(MatPaginator, { static: false }) set matPaginator(mp: MatPaginator) {
        this.todoPaginator = mp;
        this.setTodoDataSourceAttributes();
    }

    setTodoDataSourceAttributes() {
        this.todoDataSource.paginator = this.todoPaginator;
        this.todoDataSource.sort = this.todoSort;
    }

    private userPaginator: MatPaginator;
    private userSort: MatSort;

    @ViewChild(MatSort, { static: false }) set usermatSort(ms: MatSort) {
        this.userSort = ms;
        this.setUserDataSourceAttributes();
    }

    @ViewChild(MatPaginator, { static: false }) set usermatPaginator(mp: MatPaginator) {
        this.userPaginator = mp;
        this.setUserDataSourceAttributes();
    }

    setUserDataSourceAttributes() {
        this.userDataSource.paginator = this.userPaginator;
        this.userDataSource.sort = this.userSort;
    }


    /**
     * 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;
    }

}

demo-service.component.html

<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 [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 [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 [pageSizeOptions]="[10, 20, 30, 50]" showFirstLastButtons>
                                    </mat-paginator>

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

                    </ng-template>

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

    </div>
</div>

my-service.ts

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');
    }  
}
0 Answers
Related