Angular 9.1.0。 "mat-table" 不会从 GET Rest 加载数据源 Api
Angular 9.1.0. "mat-table" won't load dataSource from GET Rest Api
我试图将数据加载到 mat-table,但是当我 console.log 我试图加载的数据源时,它说数据未定义。
Link To Image Of Problem
我检索到的对象是嵌套的。
API Request
我正在学习 Angular 网站的官方教程,它是 material table examples。
也可以从这里访问 Table retrieving data through HTTP
回复:
{"BTC":{"USD":8682.55,"EUR":7851.55},"ETH":{"USD":224.8,"EUR":203.77}}
这是我目前的尝试:
(您会注意到,未使用 ngAfterViewInit(),这是由于用户输入 Api 必须等待,我仍在修改它)。
HTML:
<button (click)="removeList()">Reset</button>
<button (click)="initialiseTableData()">Display Value</button>
<div class="example-container mat-elevation-z8">
<div class="example-loading-shade" *ngIf="isLoadingResults">
<mat-spinner *ngIf="isLoadingResults"></mat-spinner>
</div>
<mat-table #table [dataSource]="dataSource" class="example-table" matSort matSortActive="created" matSortDisableClear
matSortDirection="asc">
<ng-container matColumnDef="cryptocurrency">
<mat-header-cell *matHeaderCellDef>Cryptocurrency</mat-header-cell>
<mat-cell *matCellDef="let row">{{ row.items.cryptovalue }}</mat-cell>
</ng-container>
<ng-container matColumnDef="currency">
<mat-header-cell *matHeaderCellDef>Currency</mat-header-cell>
<mat-cell *matCellDef="let row">{{ row.items.currency }}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
<mat-paginator [length]="resultsLength" [pageSize]="30">
</mat-paginator>
</div>
这是我的 .ts :
import { Component, OnInit, AfterViewInit, ViewChild } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { merge, Observable, of as observableOf } from 'rxjs';
import { catchError, map, startWith, switchMap } from 'rxjs/operators';
import { FormControl } from '@angular/forms';
import { MatSortModule, MatSort } from '@angular/material/sort';
import { MatPaginatorModule, MatPaginator } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table';
export interface TableDataApi {
items: Tabledata[];
total_count: number;
}
export interface Tabledata {
cryptovalue: {
currency: string;
};
}
@Component({
selector: 'app-crypto-chooser',
templateUrl: './crypto-chooser.component.html',
styleUrls: ['./crypto-chooser.component.css']
})
export class CryptoChooserComponent implements OnInit, AfterViewInit {
constructor(private client: HttpClient) { }
displayedColumns = ['cryptocurrency', 'currency'];
dataSource = new MatTableDataSource();
resultsLength = 0;
isLoadingResults = false;
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
initialiseTableData() {
this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0);
merge(this.sort.sortChange, this.paginator.page)
.pipe(
startWith({}),
switchMap(() => {
this.isLoadingResults = true;
return this.getCoins();
}),
map(data => {
this.isLoadingResults = false;
this.resultsLength = data.total_count;
return data.items;
}),
catchError(() => {
this.isLoadingResults = false;
return observableOf([]);
})
).subscribe(data => this.dataSource.data = data);
console.log(this.dataSource);
}
ngAfterViewInit() {
}
getCoins(): Observable<TableDataApi> {
this.generateUrl();
return this.client.get<TableDataApi>(this.urlComplete, this.httpHeader);
}
我阅读了一些关于 material table 数据源 API Angular Material API Table Docs 的文档,他们说了以下内容:
The table's source of data, which can be provided in three ways (in order of complexity):
Simple data array (each object represents one table row).
Stream that emits a data array each time the array changes.
DataSource object that implements the connect/disconnect interface.
您可以使用第一种方式(简单数据数组)。
尝试这样做以使用简单的数据数组而不是 matTableDataSource 对象。
// use simple array instead of new MatTableDataSource()
// and define your interface later, for the moments we will use any
dataSource: any[] = [];
在这里你必须修改你的订阅方法,以便将响应分配给 dataSource 变量,现在它是一个简单的数组。
initialiseTableData() {
this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0);
merge(this.sort.sortChange, this.paginator.page)
.pipe(
startWith({}),
switchMap(() => {
this.isLoadingResults = true;
return this.getCoins();
}),
map(data => {
console.info('data is an object!', data);
this.resultsLength = 0; // fix this later
this.isLoadingResults = false;
// here, data has total_count and items attributes?
// this.resultsLength = data.total_count;
// I think data is an object because you're getting
// an object as response, you're not getting a TableDataApi
// structure
return data;
}),
catchError(() => {
this.isLoadingResults = false;
return observableOf([]);
})
).subscribe(data => {
// data is an object, is not an array
// but your dataSource variable needs to be an array, so
// you have to add data into [] in order to create an array
// with your payload
this.dataSource = [data]; // <- assign data to dataSource
console.info('an array with my object', this.dataSource);
});
}
现在你添加了一个带有items和totalCount属性的接口,我不知道你为什么这样做,因为你的HTTP请求实际上有一个对象负载,也就是说:
这是你的有效载荷,它是一个对象。此对象没有 totalCount 或 items 属性。您需要修复界面。
您的数据负载是:
{"BTC":{"USD":8682.55,"EUR":7851.55},"ETH":{"USD":224.8,"EUR":203.77}}
我上面写的是把你的对象payload转成数组的方法,只把你的数据对象加到[].
删除接口并暂时使用 any,但稍后您需要定义具有正确结构的接口。
getCoins(): Observable<any> { // define interface with your correct structure
this.generateUrl();
return this.client.get<any>(this.urlComplete, this.httpHeader);
}
我试图将数据加载到 mat-table,但是当我 console.log 我试图加载的数据源时,它说数据未定义。
Link To Image Of Problem
我检索到的对象是嵌套的。 API Request
我正在学习 Angular 网站的官方教程,它是 material table examples。 也可以从这里访问 Table retrieving data through HTTP
回复:
{"BTC":{"USD":8682.55,"EUR":7851.55},"ETH":{"USD":224.8,"EUR":203.77}}
这是我目前的尝试: (您会注意到,未使用 ngAfterViewInit(),这是由于用户输入 Api 必须等待,我仍在修改它)。
HTML:
<button (click)="removeList()">Reset</button>
<button (click)="initialiseTableData()">Display Value</button>
<div class="example-container mat-elevation-z8">
<div class="example-loading-shade" *ngIf="isLoadingResults">
<mat-spinner *ngIf="isLoadingResults"></mat-spinner>
</div>
<mat-table #table [dataSource]="dataSource" class="example-table" matSort matSortActive="created" matSortDisableClear
matSortDirection="asc">
<ng-container matColumnDef="cryptocurrency">
<mat-header-cell *matHeaderCellDef>Cryptocurrency</mat-header-cell>
<mat-cell *matCellDef="let row">{{ row.items.cryptovalue }}</mat-cell>
</ng-container>
<ng-container matColumnDef="currency">
<mat-header-cell *matHeaderCellDef>Currency</mat-header-cell>
<mat-cell *matCellDef="let row">{{ row.items.currency }}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
<mat-paginator [length]="resultsLength" [pageSize]="30">
</mat-paginator>
</div>
这是我的 .ts :
import { Component, OnInit, AfterViewInit, ViewChild } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { merge, Observable, of as observableOf } from 'rxjs';
import { catchError, map, startWith, switchMap } from 'rxjs/operators';
import { FormControl } from '@angular/forms';
import { MatSortModule, MatSort } from '@angular/material/sort';
import { MatPaginatorModule, MatPaginator } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table';
export interface TableDataApi {
items: Tabledata[];
total_count: number;
}
export interface Tabledata {
cryptovalue: {
currency: string;
};
}
@Component({
selector: 'app-crypto-chooser',
templateUrl: './crypto-chooser.component.html',
styleUrls: ['./crypto-chooser.component.css']
})
export class CryptoChooserComponent implements OnInit, AfterViewInit {
constructor(private client: HttpClient) { }
displayedColumns = ['cryptocurrency', 'currency'];
dataSource = new MatTableDataSource();
resultsLength = 0;
isLoadingResults = false;
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
initialiseTableData() {
this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0);
merge(this.sort.sortChange, this.paginator.page)
.pipe(
startWith({}),
switchMap(() => {
this.isLoadingResults = true;
return this.getCoins();
}),
map(data => {
this.isLoadingResults = false;
this.resultsLength = data.total_count;
return data.items;
}),
catchError(() => {
this.isLoadingResults = false;
return observableOf([]);
})
).subscribe(data => this.dataSource.data = data);
console.log(this.dataSource);
}
ngAfterViewInit() {
}
getCoins(): Observable<TableDataApi> {
this.generateUrl();
return this.client.get<TableDataApi>(this.urlComplete, this.httpHeader);
}
我阅读了一些关于 material table 数据源 API Angular Material API Table Docs 的文档,他们说了以下内容:
The table's source of data, which can be provided in three ways (in order of complexity):
Simple data array (each object represents one table row).
Stream that emits a data array each time the array changes.
DataSource object that implements the connect/disconnect interface.
您可以使用第一种方式(简单数据数组)。
尝试这样做以使用简单的数据数组而不是 matTableDataSource 对象。
// use simple array instead of new MatTableDataSource()
// and define your interface later, for the moments we will use any
dataSource: any[] = [];
在这里你必须修改你的订阅方法,以便将响应分配给 dataSource 变量,现在它是一个简单的数组。
initialiseTableData() {
this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0);
merge(this.sort.sortChange, this.paginator.page)
.pipe(
startWith({}),
switchMap(() => {
this.isLoadingResults = true;
return this.getCoins();
}),
map(data => {
console.info('data is an object!', data);
this.resultsLength = 0; // fix this later
this.isLoadingResults = false;
// here, data has total_count and items attributes?
// this.resultsLength = data.total_count;
// I think data is an object because you're getting
// an object as response, you're not getting a TableDataApi
// structure
return data;
}),
catchError(() => {
this.isLoadingResults = false;
return observableOf([]);
})
).subscribe(data => {
// data is an object, is not an array
// but your dataSource variable needs to be an array, so
// you have to add data into [] in order to create an array
// with your payload
this.dataSource = [data]; // <- assign data to dataSource
console.info('an array with my object', this.dataSource);
});
}
现在你添加了一个带有items和totalCount属性的接口,我不知道你为什么这样做,因为你的HTTP请求实际上有一个对象负载,也就是说: 这是你的有效载荷,它是一个对象。此对象没有 totalCount 或 items 属性。您需要修复界面。
您的数据负载是:
{"BTC":{"USD":8682.55,"EUR":7851.55},"ETH":{"USD":224.8,"EUR":203.77}}
我上面写的是把你的对象payload转成数组的方法,只把你的数据对象加到[].
删除接口并暂时使用 any,但稍后您需要定义具有正确结构的接口。
getCoins(): Observable<any> { // define interface with your correct structure
this.generateUrl();
return this.client.get<any>(this.urlComplete, this.httpHeader);
}