![](/img/trans.png)
[英]I want my component not to render if data is not received from api in angular 2
[英]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-table
和mat-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.