多个 Mat Paginator 在 Angular 组件中不工作

Multiple Mat Paginator not working in Angular component

我有三种不同的 div (Post, Todo, User),根据用户选择我显示不同的 table。 例如, 默认情况下 Post 部分加载 100 records. 的 table 如果用户选择 Todo 部分,table 应该分页显示Todo条记录等

我在 angular 组件中有 three datasourcethree paginators。所有这些 table 数据都是使用 REST GET 调用 获取的。我正在获取所有数据,但分页未按预期工作。

分页仅适用于 Post 部分,其余两个 (todo and user) 分页器不工作。

请在下面找到我的代码,我在这里做错了什么 - 过去两天我一直在苦苦挣扎,无法弄清楚为什么分页对所有代码都不起作用。

如果您能帮助我解决以下问题,我们将不胜感激。提前感谢您的帮助。谢谢!

Post has total 100 records

Todo has total 200 records

User has total 10 records

我的-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 文件

<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>

服务 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');
    }  
}

因为您使用的是*ngIf,执行ngAfterViewInit时渲染的模板没有元素todouser

*ngif修改为[hidden]并反转条件即可避免。

<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'">