【问题标题】:Angular server side pagination with dynamic table component具有动态表格组件的角度服务器端分页
【发布时间】:2020-05-18 18:48:36
【问题描述】:

我编写了以下代码来创建一个动态表格组件来加载数据,现在我正在尝试使用这个组件来实现服务器端分页:

table.component.ts

import { Component, OnInit, Input, ViewChild, SimpleChanges } from '@angular/core';
import { MatSort } from '@angular/material/sort';
import { MatPaginator } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table';

@Component({
  selector: 'app-table',
  templateUrl: './table.component.html',
  styleUrls: ['./table.component.scss']
})
export class TableComponent implements OnInit {
  tableDataSrc: any;
  // tslint:disable-next-line: no-input-rename
  @Input('tableColumns') tableCols: string[];
  @Input() tableData: {}[] = [];

  @ViewChild(MatSort, { static: true }) sort: MatSort;
  @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;


  constructor() { }

  ngOnInit() {
  //   this.tableDataSrc = new MatTableDataSource(this.tableData);
  //   this.tableDataSrc.sort = this.sort;
  //   this.tableDataSrc.paginator = this.paginator;
  }

  ngOnChanges(changes: SimpleChanges) {
    if(changes.tableData.currentValue) {
        this.tableDataSrc = new MatTableDataSource(this.tableData);
        this.tableDataSrc.sort = this.sort;
        this.tableDataSrc.paginator = this.paginator;
    }
}

}

table.component.html

<div class="mat-elevation-z8">


<table mat-table [dataSource]="tableDataSrc" matSort class="mat-elevation-z8">
    <ng-container *ngFor="let col of tableCols">
    <ng-container matColumnDef="{{ col }}">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>
        {{ col | titlecase }}
        </th>
        <td mat-cell *matCellDef="let profile">{{ profile[col] }}</td>
    </ng-container>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="tableCols"></tr>
    <tr mat-row *matRowDef="let row; columns: tableCols"></tr>
</table>

<mat-paginator [pageSizeOptions]="[1, 2, 3, 5, 10, 20]" showFirstLastButtons></mat-paginator>
</div>

team.service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Team } from "../models/team";

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

  constructor(
    private http:HttpClient,
  ) { }

  getTeams(page:number=1){
    return this.http.get<any>('http://localhost:8000/api/teams', {
      params: new HttpParams()
        .set("page", page.toString())
    }
    )
  }
}

teams.component.ts

import { Component, OnInit } from '@angular/core';
import { first } from 'rxjs/operators';
import { TeamService } from 'src/app/services/team.service';

@Component({
  selector: 'app-teams',
  templateUrl: './teams.component.html',
  styleUrls: ['./teams.component.scss']
})
export class TeamsComponent implements OnInit {
  public teams : any; 

  tableCols = ['sofascore_id', 'name'];

  constructor(private teamService : TeamService) { }

  ngOnInit(): void {
    this.teamService.getTeams().pipe(first()).subscribe(
      data => {
        this.teams = data.results
      },
      error => {
        console.log(error.error)
      }
    ) 
  }

}

teams.component.html

<app-table [tableData]="teams" [tableColumns]="tableCols"></app-table>

我的问题:我将如何实现服务器端分页?我知道getTeams 函数中的页面参数丢失了,但是我如何将它从分页器传递给那个。我查看了多个教程和示例(例如https://material.angular.io/components/table/examples),但我似乎无法弄清楚

【问题讨论】:

    标签: angular typescript


    【解决方案1】:

    您可以使用来自MatPaginator@Output() page: EventEmitter&lt;PageEvent&gt; 事件并将该事件委托给TeamsComponent 并使用它来触发服务请求。见here for PageEvent

    table.component.ts 构造函数之前添加以下内容;

    @Output() pageChange = new EventEmitter<PageEvent>();
    

    table.component.html中;

    <mat-paginator (page)="pageChange.emit($event)"
                   [pageSizeOptions]="[1, 2, 3, 5, 10, 20]" 
                   showFirstLastButtons>
    </mat-paginator>
    

    teams.component.html中;

    <app-table (pageChange)="handlePageChange($event)" [tableData]="teams" [tableColumns]="tableCols"></app-table>
    

    teams.componet.ts

      ngOnInit(): void {
        this.fetchTeams(); 
      }
    
      fetchTeams(pageNumber = 1){
        this.teamService.getTeams(pageNumber).pipe(first()).subscribe(
          data => {
            this.teams = data.results
          },
          error => {
            console.log(error.error)
          }
        )
      }
    
      handlePageChange(event: PageEvent) {
        this.fetchTeams(event.pageIndex)
      }
    

    除了您的问题之外,您还需要更改getTeams api,同时考虑页面大小。否则,无论用户从MatPaginator 选择什么页面大小,您的服务响应将始终在每页提供相同数量的项目。或者,您可以在 MatPaginator 上设置固定页面大小(与服务器响应大小相同),即在 mat-paginator 上设置 [pageSizeOptions]="[15]",假设您的服务器响应始终返回 15 个项目。

    【讨论】:

    • 但是分页器是如何知道总条目数的呢?我的服务器端当时只返回 15 个项目
    • 好点:) 当TeamsComponent 首次加载时,您应该从服务器获取项目总数,然后将其传递给TableComponent 并将其分配给mat-paginatorlength 属性。
    • 谢谢,pageChange 函数似乎没有正确传递,因为我使用您的代码得到它不存在的错误
    • 您是否将@Output() pageChange = new EventEmitter&lt;PageEvent&gt;(); 添加到TeamsComponent?确切的错误是什么。你能把它贴在这里吗?
    • 是的,我做到了,这是错误Property 'pageChange' does not exist on type 'TableComponent'.
    猜你喜欢
    • 2023-02-15
    • 2017-01-12
    • 2016-07-19
    • 2019-10-17
    • 2018-07-27
    • 1970-01-01
    • 1970-01-01
    • 2018-12-04
    • 2015-12-05
    相关资源
    最近更新 更多