【问题标题】:Angular 9.1.0. "mat-table" won't load dataSource from GET Rest Api角 9.1.0。 “mat-table”不会从 GET Rest Api 加载数据源
【发布时间】:2020-06-12 23:32:17
【问题描述】:

我正在尝试将数据加载到 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);
  }

【问题讨论】:

  • 尝试在订阅方法上打印您的数据。这样做.subscribe(data =&gt; {console.log(data); this.dataSource.data = data;});你能这样看你的数据吗?
  • 用“新的 MatTableDataSource();” ,它只会给我“未定义”。
  • 如果您使用我在console.log(data); 之前注释的代码片段显示未定义?还是显示 API 负载?
  • 是的,使用 dataSource: Tabledata[] = [],它给了我 undefined。
  • 你能在地图运算符上打印数据变量吗? map(data =&gt; { console.info('what is data?', data); this.isLoadingResults = false; this.resultsLength = data.total_count; return data.items; }),

标签: angular api undefined datasource mat-table


【解决方案1】:

我阅读了一些关于材料表数据源 API Angular Material API Table Docs 的文档,他们说如下:

表格的数据来源,可以通过三种方式提供(按复杂程度排序):

简单的数据数组(每个对象代表一个表格行)。

每次数组更改时发出数据数组的流。

实现连接/断开接口的DataSource对象。

你可以使用第一种方式(简单数据数组)。

尝试这样做以便使用简单的数据数组而不是 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}}

我上面写了将你的对象有效负载转换为数组的方法,只需将你的数据对象添加到[]中。

删除接口并暂时使用any,但您需要稍后定义具有正确结构的接口。

  getCoins(): Observable<any> { // define interface with your correct structure
    this.generateUrl();
    return this.client.get<any>(this.urlComplete, this.httpHeader);
  }

【讨论】:

  • 好的,我像你说的那样设置了dataSource,并更新了函数以在Tabledata接口中返回响应,如下所示: getCoins(): Observable { this.generateUrl();返回 this.client.get(this.urlComplete, this.httpHeader); } console.log 数据给了我一个像它应该的对象:{LTC: {…}, USDT: {…}, BCH: {…}} LTC: {EUR: 54.24} USDT: {EUR: 0.9067} BCH : {EUR: 284.24} 但我确实收到一个错误:提供的数据源与数组、Observable 或 DataSource 不匹配,这告诉我映射失败?
  • 不,你必须保留你的代码,只使用dataSource: Tabledata[] = [];而不是dataSource = new MatTableDataSource();,因为你的getCoins方法是正确的,不要改变它
  • 我编辑了答案,因为我在您的代码中发现了一些错误。
  • 好的,很酷,我现在很接近了,一个带有我的对象的数组 [{…}] 0:XRP:{EUR:0.2144} LTC:{EUR:54.36} USDT:{EUR:0.908 } proto: 对象长度: 1 proto: Array(0), 对象数组存储在dataSource的数组中!但是,它仍然没有在表格上显示数据,它只显示一个空白行。
  • 是的,这是正确的,因为在您的 HTML 代码中,您尝试从 {{ row.items.cryptovalue }} 获取属性,而您的结构没有这些属性。
猜你喜欢
  • 1970-01-01
  • 2020-01-25
  • 2018-12-18
  • 2021-07-08
  • 2020-07-10
  • 2019-07-01
  • 2020-12-18
  • 1970-01-01
  • 2018-10-22
相关资源
最近更新 更多