Angular 9.1.0. "mat-table" не будет загружать источник данных из GET Rest Api - PullRequest
0 голосов
/ 28 февраля 2020

Я пытаюсь загрузить данные в mat-table, но когда я пытаюсь загрузить dataSource, который я пытаюсь загрузить, console.log сообщает, что данные не определены.

Ссылка на изображение Проблема

Полученный мной объект вложен. Запрос API

Я следую официальному руководству с сайта Angular, и это примеры таблиц материалов . Также доступно здесь Таблица извлечения данных по HTTP

Reposnse:

{"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);
  }

1 Ответ

0 голосов
/ 29 февраля 2020

Я прочитал некоторую документацию об API источника данных таблицы материалов Angular Документы API таблицы материалов , и они говорят следующее:

Источник данных таблицы, который может быть представлен тремя способами (в порядке сложности):

Простой массив данных (каждый объект представляет одну строку таблицы).

Поток, который выдает массив данных каждый раз, когда массив изменяется.

Объект 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);
      });
  }

Теперь вы добавили интерфейс с элементами и атрибутами totalCount, я не знаю, почему вы это сделали, потому что ваш HTTP-запрос на самом деле имеет полезная нагрузка объекта, то есть это ваша полезная нагрузка, это объект. Этот объект не имеет атрибутов totalCount или items. Вы должны исправить свой интерфейс.

Ваша полезная нагрузка данных:

{"BTC":{"USD":8682.55,"EUR":7851.55},"ETH":{"USD":224.8,"EUR":203.77}}

Я пишу выше способ преобразования полезной нагрузки вашего объекта в массив, только добавьте ваш объект данных в [].

Удалите интерфейс и используйте любой для моментов, но позже вам нужно будет определить интерфейс с правильной структурой.

  getCoins(): Observable<any> { // define interface with your correct structure
    this.generateUrl();
    return this.client.get<any>(this.urlComplete, this.httpHeader);
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...