Hello friendly early birds!
I fetch data from an API with following response:
My service returns the Observable<Movie[]> object to my component. In the HTML of the component, I want to use the async pipe instead of subscription. So I don't have to unsub on the components to prevent memory leaks.
movie-list.component.html:
<div >
<div *ngFor="let movie of movies$ | async">
<app-movie
[movie]="movie"
></app-movie>
</div>
</div>
movie-list.component.ts:
export class MovieListComponent implements OnInit {
movies$!: Observable<Movie[]>;
constructor(private movieService: MovieService) { }
ngOnInit(): void {
this.movies$ = this.movieService.getMostPopularMovies();
}
}
movie-service.ts:
})
export class MovieService {
private apiKey: string = environment.apiKey;
private apiMostPopularMovies: string = 'https://api.themoviedb.org/3/movie/popular';
constructor(private http: HttpClient) { }
getMostPopularMovies(): Observable<Movie[]> {
let params = new HttpParams();
params = params.set('api_key', this.apiKey);
return this.http.get<Movie[]>(this.apiMostPopularMovies, {params});
}
}
Movie.component.ts:
export class MovieComponent implements OnInit {
@Input() movie!: Movie;
constructor() { }
ngOnInit(): void {
}
}
My Movie model just have a title, poster_path and vote_average field. The field have the same names as the the response in results array have. I don't need anything else from the response.
Somehow I have to map the fields from the response from results array to my Movie model. Can someone explain how to do this with async pipe?
CodePudding user response:
Well, the problem is your response actually is not Movie[]
but your response.results
is.
To solve this, you could use map
operator in rxjs. If you could use the following code in your service, async pipe would work fine.
export class MovieService {
private apiKey: string = environment.apiKey;
private apiMostPopularMovies: string = 'https://api.themoviedb.org/3/movie/popular';
constructor(private http: HttpClient) { }
getMostPopularMovies(): Observable<Movie[]> {
let params = new HttpParams();
params = params.set('api_key', this.apiKey);
return this.http
.get<{results: Movie[]}>(this.apiMostPopularMovies, {params})
.pipe(map(response => response.results));
}
}
CodePudding user response:
If I understood you correctly, you can try this in your service:
mappedMoviesObs: Observable<Movies[]> = this.getMostPopularMovies().pipe(
map((movies: Movies[]) => movies.forEach((movie) => { // do mapping})
);
And in html use mappedMoviesObs
instead of movies$
.