簡體   English   中英

僅在從REST API接收數據后,我應該如何使用分頁呈現Angular MatTable?

[英]How should I render a Angular MatTable with pagination only after data is received from a REST API?

我正在嘗試創建一個表組件,用戶可以在其中添加要加載到數據中的REST端點。 數據應該是一個任意對象的數組,因此這里不一定有可能沒有嚴格的模式。

問題是我無法獲取表,並且在我在REST端點上發出請求之前等待呈現的是paginator。 我有一個版本可以使分頁工作,但是在加載數據之前,paginator(和空表)仍然出現。

我嘗試過使用AfterViewChecked,以及初始化paginator和table的各種不同的地方。

Stackblitz樣本在這里。 請注意,您不必在模態中輸入有效的端點,因為它是從虛擬端點獲取的。 我將模態盡可能接近我的默認狀態。

component.ts文件:

import { Component, OnInit, ViewChild } from '@angular/core';
import { MatPaginator, MatTable, MatTableDataSource } from '@angular/material';
import { DomSanitizer } from '@angular/platform-browser';
import { RestService } from '../rest.service';

@Component({
    providers: [RestService],
    selector: 'table-widget',
    styleUrls: ['./table-widget.component.scss'],
    templateUrl: './table-widget.component.html',
})

export class TableWidgetComponent implements OnInit {
    public dataSource: MatTableDataSource<any> = new MatTableDataSource();
    // map of header names (which are keys in series) to whether they should be visible
    public headers: Map<string, boolean>;
    public headerKeys: string[];

    @ViewChild(MatTable) private table: MatTable<any>;
    @ViewChild(MatPaginator) private paginator: MatPaginator;

    // array of header titles, to get arround ExpressionChangedAfterItHasBeenCheckedError
    private restEndpoint: string;
    private editModalVisibility: boolean;

    constructor(private restService: RestService, private sanitizer: DomSanitizer) { }

    // called each time an AppComponent is initialized
    public ngOnInit(): void {
        this.headers = new Map<string, boolean>();
        this.editModalVisibility = false;
        this.dataSource.paginator = this.paginator;
    }

    public eventFromChild(data: string): void {
        this.restEndpoint = data;
        // return value of rest call
        this.restService.getFromEndpoint(this.restEndpoint)
            .subscribe((series) => {
                this.dataSource.data = series;
                this.table.renderRows();

                // set keys, unless series is empty
                if (series.length > 0) {
                    Object.keys(this.dataSource.data[0]).forEach((value) => {
                        this.headers.set(value, true);
                    });
                }
                this.headerKeys = Array.from(this.headers.keys());
            });
    }
    .
    .
    .
}

和HTML文件:

<div [ngClass]="['table-widget-container', 'basic-container']">
  <div [ngClass]="['table-container']">
    <mat-table [ngClass]="['mat-elevation-z8']" [dataSource]="dataSource">
      <ng-container *ngFor="let header of getVisibleHeaders()" matColumnDef={{header}}>
        <mat-header-cell *matHeaderCellDef> {{header | titlecase}} </mat-header-cell>
        <mat-cell *matCellDef="let entry"> {{entry[header]}} </mat-cell>
      </ng-container>

      <mat-header-row *matHeaderRowDef="getVisibleHeaders()"></mat-header-row>
      <mat-row *matRowDef="let row; columns: getVisibleHeaders();"></mat-row>
    </mat-table>

    <mat-paginator #paginator [pageSize]="5" [pageSizeOptions]="[5, 11, 20]"></mat-paginator>

  </div>
  <button *ngIf="dataSource.data.length" (click)="openModal()" class="add-rest-button">
    Edit Table
  </button>
  <add-rest-button (sendDataToParent)="eventFromChild($event)"></add-rest-button>
</div>

當我嘗試將*ngIf="dataSource.data.length"mat-tablemat-paginator ,顯示的是paginator但是沒有“鏈接”到表,或者表中沒有數據,並且我得到以下錯誤:

TypeError: Cannot read property 'renderRows' of undefined

我知道發生此錯誤是因為由於ngIf指令而未定義表,但我不確定如何有效地隱藏表。

將屬性添加到組件isInitialized

將您的方法更新為:

public eventFromChild(data: string): void {
        console.log(this.dataSource.data.length);
        this.restEndpoint = data;
        // TODO: handle errors of restService
        // return value of rest call
        this.restService.getFromEndpoint(this.restEndpoint)
            .subscribe((series) => {
               this.isInitialized = true;
               ...
             }

和你的HTML:

<div *ngIf="isInitialized" [ngClass]="['table-widget-container', 'basic-container']">
.
.
.
</div>

我找到了解決這個問題的方法,但我不會說它解決了根本問題; 在數據准備好之前,只需隱藏表和分頁器的容器。

首先,我將HTML中的第2行更改為:

<div [ngClass]="['table-container']" [style.display]="getTableVisibleStyle()">

然后我將以下函數添加到TS文件中:

    public getTableVisibleStyle() {
        let style: string = 'none';
        if (this.tableVisibility) {
            style = 'block';
        }
        // have to do this to get past overzealous security
        return this.sanitizer.bypassSecurityTrustStyle(style);
    }

其中tableVisibility是在tableVisibility中設置為false的布爾值,然后在更新數據時更改為true

它確實工作得很好,雖然看起來很hacky而且不是特別健壯。 如果我發現一種更好的方法,我可能會在以后重新審視這個問題。

您可以執行以下操作來完成此操作。

不要初始化dataSource變量。

public dataSource: MatTableDataSource<any>;

table-container你可以*ngIf="dataSource"

<div [ngClass]="['table-container']" *ngIf="dataSource">

然后在收到數據時初始化變量。

this.dataSource = new MatTableDataSource();
this.dataSource.data = series;
this.table.renderRows();

要再次隱藏它,請將變量null

this.dataSource = null;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM