2017-02-16 42 views
0

Я делаю простую поисковую систему для данных фильма, используя API omdbapi.com. Я настроил службы для извлечения данных и компоненты для создания представления, но когда я пытаюсь подключиться к HTML я получаю сообщение об ошибке:Как отображать результаты после извлечения JSON из внешнего источника в Angular2

Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays. Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.

класс Movie

export class Movie { 
    constructor(
     Title: string, 
     Year: string, 
     Rated: string, 
     Released: string, 
     Runtime: string, 
     Genre: string, 
     Director: string, 
     Writer: string, 
     Actors: string, 
     Plot: string, 
     Language: string, 
     Country: string, 
     Awards: string, 
     Poster: string, 
     Metascore: string, 
     imdbRating: string, 
     imdbVotes: string, 
     imdbID: string, 
     Type: string, 
     Response: string 
    ) {} 

} 

Вот мой компонент:

import { Component, OnInit } from '@angular/core'; 
import { Http, Response } from '@angular/http'; 
import { Observable } from 'rxjs/Observable'; 
import { Subject } from 'rxjs/Subject'; 

//observable class extensions 
import 'rxjs/add/observable/of'; 
import 'rxjs/add/operator/switchMap'; 
import 'rxjs/add/operator/map'; 
//observable operators 
import 'rxjs/add/operator/catch'; 
import 'rxjs/add/operator/debounceTime'; 
import 'rxjs/add/operator/distinctUntilChanged'; 

import { MovieSearchService } from './movie-search.service'; 
import { Movie } from './movie'; 

@Component({ 
    selector: 'movie-search', 
    templateUrl: './movie-search.component.html', 
    styleUrls: ['./movie-search.component.css'], 
    providers: [MovieSearchService] 
}) 

export class MovieSearchComponent implements OnInit { 
    movies: Observable<Movie[]>; 
    private searchTerms = new Subject<string>(); 

    constructor(
     private movieSearchService: MovieSearchService, 
     private http: Http 
    ) {} 

    search(term:string) { 
     return this.searchTerms.next(term); 
    } 

    ngOnInit(): void { 
     this.movies = this.searchTerms 
     .debounceTime(300) // wait 300ms after each keystroke before considering the term 
     .distinctUntilChanged() // ignore if next search term is same as previous 
     .switchMap(term => term // switch to new observable each time the term changes 
     // return the http search observable 
     ? this.movieSearchService.search(term) 
      // or the observable of empty heroes if there was no search term 
     : Observable.of<Movie[]>([]) 
     ) 
     .catch(error => { 
      console.log("--------- Error -------"); 
      console.log(error); 

      return Observable.of<Movie[]>([]); 
     })  
    } 
} 

Это услуга

import { Injectable } from '@angular/core'; 
import { Http, Jsonp } from '@angular/http'; 

import { Observable} from 'rxjs/Observable'; 
import 'rxjs/add/operator/map'; 

import { Movie } from './movie'; 

@Injectable() 
export class MovieSearchService { 
    constructor(
     private http: Http, 
     private jsonp: Jsonp 
    ) {} 

    search(term: string): Observable<Movie[]> { 
     return this.http 
      .get(`http://www.omdbapi.com/?s=${term}`) 
      .map(response => { 
       return response.json().each() as Movie[] 
      }) 
    } 
} 

И вид

<div class="col-xs-12"> 
    <input #searchBox id="search-box" /> 
    <button (click)="search(searchBox.value)">Search</button> 
</div> 

<ul *ngIf="movies"> 
    <li *ngFor="let movie of movies"> 
     {{ movie.title }} 
    </li> 
</ul> 

Как я могу сделать вид показать название фильма для каждого фильма? Заранее благодарим за ваше время.

+0

Возможный дубликат [http with Observable in Angular 2 can not use data] (http://stackoverflow.com/questions/41961693/http-with-observable-in-angular-2-cant-use-data) – AngularChef

+0

Пожалуйста, разместите образец структуры JSON, возвращенный API –

ответ

1

Всегда проверяйте вкладку сети, чтобы узнать, действительно ли вы получаете данные и как выглядят эти данные.

Тестирование этого. Видимо, вы в первую очередь необходимо создать свой адрес, как это:

return this.http.get('http://www.omdbapi.com/?s='+term) 

Тогда, как и в ответ, он построен так:

{"Search":[{"Title":"24","Year":"2001–2010","imdbID".... 

Так что вам нужно извлечь, чтобы получить массив:

.map(response => {response.json().Search}) 

и подписаться на компоненте:

this.movieSearchService.search(term) 
    .subscribe(d => this.movies = d) 

, а затем, если вы хотите отображать название:

<ul *ngIf="movies"> 
    <li *ngFor="let movie of movies"> 
     {{ movie.Title }} 
    </li> 
</ul> 

Обратите внимание на Search и Title в вышеуказанных кодов. Это чувствительно к регистру, поэтому вам нужно, например, использовать {{ movie.Title }} с капиталом T, чтобы иметь возможность отображать ваши данные.

Это должно прояснить ситуацию! :)

+0

Спасибо за ваш ответ @ AJT_82 –

+0

Добро пожаловать! :) как сказано, используйте свои инструменты разработчика, например, в chrome на F12. Затем откройте вкладку вашей сети и проверьте запрос и посмотрите, есть ли вообще ответ. С вашим URL-адресом был пустой ответ, и поэтому вы не могли перебирать. Вот фотография. Проверьте детали, на которых я отмечен желтым цветом :) http://imgur.com/a/RuClo – Alex

+0

Извините, это отправил мой ответ случайно, прежде чем я закончил. Я получаю сообщение об ошибке:

Argument of type '(term: string) => Subscription | Observable' is not assignable to parameter of type '(value: string, index: number) => ObservableInput'. Type 'Subscription | Observable' is not assignable to type 'ObservableInput'. 
Я считаю, что это потому, что я объявляю фильмы в качестве наблюдаемого объекта, таких как фильмы: Наблюдаемое Фильм содержит структуру (название, год и т.д. ...) Если я не объявляю его наблюдаемым, как объявить переменные фильмы? –