Проблема
У меня проблема с привязкой данных JSON к таблице данных Angular Material.
Фон
Я разрабатываю небольшое приложение, которое предназначено для предоставления пользователям информации о фильмах. Вызов API инициируется после того, как пользователь запускает поиск. Затем это должно заполнить таблицу данных данными ответа.
Хотя я могу успешно выполнить вызов API, данные в таблицу данных не передаются:
Ответ API в инструментах разработчика
Кроме того, в консоли не отображаются ошибки, и я могу заполнить таблицу тестовыми данными.
Вот код:
api-calls.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 https:HttpClient){}
public getFilms(searchTerm): Observable<any> {
const apiUrl = 'https://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;
}
Подтвердите, что данные, которые возвращаются, имеют ожидаемую форму и не вложены или что-то в этом роде — person RuffMingani schedule 08.03.2020
Интересно, что с кодом, который я предоставил, когда я пробую console.log (data) или console.log (dataSource), он возвращается с undefined. Попробую получить запись данных в консоль. — person RuffMingani schedule 08.03.2020
Значит, проблема в форме мероприятия. Оцените это: omdbapi.com/?apikey=b1464edd&s=hello обратите внимание на ответ фильмы вложены в свойство поиска, поэтому вам также нужно будет добавить другую услугу, например return this.http.get(fullLink).pipe(map(r => r.Search))
— person RuffMingani schedule 08.03.2020
Добавьте код для app-search
— person RuffMingani schedule 08.03.2020
Спасибо, return this.http.get(fullLink).pipe(map(r => r.Search))
. Кроме того, мне потребовалось изменить film.model.ts из-за чувствительности к регистру. — person RuffMingani schedule 08.03.2020
Теперь он работает? — person RuffMingani schedule 08.03.2020
Это да! Извините, вчера я не закончила фразу. Спасибо за твою помощь. — person RuffMingani schedule 09.03.2020
JSON, возвращаемый API, имеет следующую форму
Поэтому вам необходимо внести некоторые коррективы.
Во-первых, вам нужно спроецировать ответ, извлекая свойство
Search
, которое содержит массив фильмов. Это должно быть сделано в вашей службе (обратите внимание на улучшенное использование типов)api-calls.service.ts
Затем нам нужно объявить имена свойств в интерфейсе модели, чтобы правильно описать форму пленок в ответе.
film.model.ts
Теперь давайте настроим сам компонент, чтобы немного улучшить типы
app.component.ts
Обратите внимание, как было улучшено использование типов, чтобы ограничить имена столбцов, чтобы они оставались синхронизированными между компонентом и службой. Также обратите внимание, что избыточная информация о типе была улучшена, чтобы использовать преимущества вывода типа, вытекающего из улучшенной сигнатуры типа метода службы.