Невозможно привязать данные к Angular Таблице данных материала - PullRequest
2 голосов
/ 08 марта 2020

Issue

У меня проблема с привязкой JSON данных к Angular таблице данных материала.

Фон

Я занимаюсь разработкой небольшого приложения, предназначенного для предоставления пользователям информации о фильмах. Вызов API инициируется после запуска пользователем поиска. Это должно затем заполнить таблицу данных данными ответа.

Хотя я могу успешно выполнить вызов API, в таблицу данных не передаются никакие данные:

Ответ API в Dev Tools

Кроме того, нет ошибки отображаются в консоли, и я могу заполнить таблицу тестовыми данными.

Вот код:

api-Call.Service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpResponse } from '@angular/common/http';
import { Observable, of } from 'rxjs';

@Injectable()
export class ApiService {
constructor(private http:HttpClient){}

public getFilms(searchTerm): Observable<any> {
  const apiUrl = 'http://www.omdbapi.com/?apikey=b1464edd&s=';
  const fullLink = apiUrl + searchTerm
  return this.http.get(fullLink)
}}

app.component.ts

import { Component, OnInit } from '@angular/core';
import { Films } from './models/films.model';
import { ApiService } from './services/api-calls.service';
import { MatTableDataSource } from '@angular/material';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent implements OnInit{

constructor(private apiService:ApiService) {}

displayedColumns: string[] = ['title', 'year', 'imdbID', 'poster', 'type']
dataSource: MatTableDataSource<any[]>;
searchTerm = '';

handleSearch(event) {
  if(event.action === 'SEARCH') {
    this.searchTerm = event.query
    this.apiService.getFilms(this.searchTerm).subscribe(
      data => this.dataSource = new MatTableDataSource<Films[]>(data)
    )}
  }

  ngOnInit() {
  }
}

app.component. html (функция поиска, описанная в классе контейнера, обрабатывается в другом компоненте)

<div class = "container">
      <mat-card>
          <h2>Lightweight IMDb Search Engine</h2>
          <app-search (searchEvent)="handleSearch($event)"></app-search>
      </mat-card>

      <div>
        <mat-table [dataSource] = "dataSource">
          <ng-container matColumnDef="title">
            <mat-header-cell *matHeaderCellDef> Title </mat-header-cell>
            <mat-cell *matCellDef="let films"> {{ films.title }}</mat-cell>
          </ng-container>
          <ng-container matColumnDef="year">
            <mat-header-cell *matHeaderCellDef> Year </mat-header-cell>
            <mat-cell *matCellDef="let films"> {{ films.year }}</mat-cell>
          </ng-container>
          <ng-container matColumnDef="imdbID">
            <mat-header-cell *matHeaderCellDef> imdbID </mat-header-cell>
            <mat-cell *matCellDef="let films"> {{ films.imdbID }}</mat-cell>
          </ng-container>
          <ng-container matColumnDef="poster">
            <mat-header-cell *matHeaderCellDef> Poster </mat-header-cell>
            <mat-cell *matCellDef="let films"> {{ films.poster }}</mat-cell>
          </ng-container>
          <ng-container matColumnDef="type">
            <mat-header-cell *matHeaderCellDef> Type </mat-header-cell>
            <mat-cell *matCellDef="let films"> {{ films.type }}</mat-cell>
          </ng-container>
          <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
          <mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
        </mat-table>
      </div>
  </div>

film.model.ts

export interface Films {
    title: string;
    year: string;
    imdbID: string;
    poster: string;
    type: string;
}

1 Ответ

1 голос
/ 09 марта 2020

Возвращаемое API значение JSON имеет следующую форму

{
  "Search": [
    {"Title":"Hello, My Name Is Doris","Year":"2015","imdbID":"tt3766394","Type":"movie","Poster":"https://m.media-amazon.com/images/M/MV5BMTg0NTM3MTI1MF5BMl5BanBnXkFtZTgwMTAzNTAzNzE@._V1_SX300.jpg"},
    // etc.
  ]
} 

Поэтому вам необходимо внести некоторые корректировки.

Во-первых, вам необходимо спроецировать ответ, извлекая Search свойство, которое содержит массив фильмов. Это должно быть сделано в вашем сервисе (обратите внимание на улучшенное использование типов)

api-Call.Service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

import Film from './models/film.model';

@Injectable()
export class ApiService {
  constructor(private http:HttpClient){}

  getFilms(searchTerm): Observable<Film[]> {
    const apiUrl = 'http://www.omdbapi.com/?apikey=b1464edd&s=';
    const fullLink = apiUrl + searchTerm;
    type Response = { Search: Film[] };
    return this.http.get<Response> (fullLink)
      .pipe(map(response => response.Search));
  }
}

Затем мы должны объявить свойство имена в интерфейсе модели для правильного описания формы пленки в ответе

film.model.ts

export default interface Film {
    Title: string;
    Year: string;
    imdbID: string;
    Poster: string;
    Type: string;
}

Теперь давайте настроим сам компонент для улучшения типы немного

app.component.ts

import { Component } from '@angular/core';
import { ApiService } from './services/api-calls.service';
import { MatTableDataSource } from '@angular/material';

import Film from './models/film.model';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {

  constructor(private apiService:ApiService) {}

  displayedColumns: (keyof Film)[] = ['Title', 'Year', 'imdbID', 'Poster', 'Type'];
  dataSource?: MatTableDataSource<Film[]>;
  searchTerm = '';

  handleSearch({ action, query }) {
    if (action === 'SEARCH' && query) {
      this.searchTerm = query;
      this.apiService.getFilms(this.searchTerm)
        .subscribe(films => this.dataSource = new MatTableDataSource(films));
    }
  }
}

Обратите внимание, как улучшено использование типов, чтобы ограничить имена столбцов, чтобы они оставались в синхронизации c между компонентом и службой. Также обратите внимание, что избыточная информация о типах была улучшена, чтобы использовать в своих интересах вывод типа, вытекающий из улучшенной сигнатуры типа метода службы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...