Skip to content

The Movie Service and HTTP Integration

Before writing any component, create the data layer: interfaces that describe TMDb’s response shapes, and a service with methods for every API call the app needs.

Create src/app/models/movie.model.ts:

export interface Movie {
id: number;
title: string;
overview: string;
poster_path: string | null;
backdrop_path: string | null;
release_date: string;
vote_average: number;
vote_count: number;
genre_ids: number[];
}
export interface Genre {
id: number;
name: string;
}
export interface CastMember {
id: number;
name: string;
character: string;
profile_path: string | null;
}
export interface MovieDetail extends Movie {
genres: Genre[];
runtime: number | null;
tagline: string;
credits?: {
cast: CastMember[];
};
}
export interface MoviesResponse {
results: Movie[];
total_pages: number;
total_results: number;
}

Note credits?: is optional — TMDb only includes it when you pass append_to_response=credits.

Create src/app/core/tmdb.config.ts:

import { environment } from '../../environments/environment';
export const TMDB_API_KEY = environment.tmdbApiKey;
export const TMDB_BASE = 'https://api.themoviedb.org/3';
export function posterUrl(path: string | null, size = 'w500'): string {
return path
? `https://image.tmdb.org/t/p/${size}${path}`
: '/no-poster.svg';
}
export function backdropUrl(path: string | null): string {
return path
? `https://image.tmdb.org/t/p/w1280${path}`
: '';
}

Create src/app/services/movie.ts:

import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, map } from 'rxjs';
import {
Movie, MovieDetail, MoviesResponse, Genre
} from '../models/movie.model';
import { TMDB_API_KEY, TMDB_BASE } from '../core/tmdb.config';
@Injectable({ providedIn: 'root' })
export class MovieService {
private http = inject(HttpClient);
private readonly params = { api_key: TMDB_API_KEY };
getPopular(): Observable<Movie[]> {
return this.http.get<MoviesResponse>(
`${TMDB_BASE}/movie/popular`, { params: this.params }
).pipe(map(r => r.results));
}
getTrending(): Observable<Movie[]> {
return this.http.get<MoviesResponse>(
`${TMDB_BASE}/trending/movie/week`, { params: this.params }
).pipe(map(r => r.results));
}
getTopRated(): Observable<Movie[]> {
return this.http.get<MoviesResponse>(
`${TMDB_BASE}/movie/top_rated`, { params: this.params }
).pipe(map(r => r.results));
}
getDetail(id: number): Observable<MovieDetail> {
return this.http.get<MovieDetail>(
`${TMDB_BASE}/movie/${id}`,
{ params: { ...this.params, append_to_response: 'credits' } }
);
}
search(query: string): Observable<MoviesResponse> {
return this.http.get<MoviesResponse>(
`${TMDB_BASE}/search/movie`,
{ params: { ...this.params, query } }
);
}
discover(genre: string, year: string, sortBy: string): Observable<Movie[]> {
const params: Record<string, string> = { ...this.params, sort_by: sortBy };
if (genre) params['with_genres'] = genre;
if (year) params['primary_release_year'] = year;
return this.http.get<MoviesResponse>(
`${TMDB_BASE}/discover/movie`, { params }
).pipe(map(r => r.results));
}
getGenres(): Observable<Genre[]> {
return this.http.get<{ genres: Genre[] }>(
`${TMDB_BASE}/genre/movie/list`, { params: this.params }
).pipe(map(r => r.genres));
}
}

Update src/app/app.config.ts:

import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideHttpClient } from '@angular/common/http';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient()
]
};
  1. Create movie.model.ts with all the interfaces above.
  2. Create tmdb.config.ts with the API key, base URL, and helper functions.
  3. Create movie.ts (the service) with all seven methods.
  4. Update app.config.ts to include provideHttpClient().
  5. Inject MovieService into AppComponent temporarily and call getTrending() in ngOnInit. Subscribe and log the results to confirm the API call works.
  6. Remove the test code from AppComponent.
  • Define interfaces for Movie, MovieDetail, Genre, CastMember, and MoviesResponse in models/movie.model.ts.
  • Put TMDb constants and URL helpers in core/tmdb.config.ts, reading the API key from the environment file.
  • MovieService has methods for all API calls: getPopular, getTrending, getTopRated, getDetail, search, discover, getGenres.
  • Register HttpClient with provideHttpClient() in app.config.ts.