Skip to main content

Overview

ScreenPulse’s search feature allows users to find movies, TV shows, and series using the OMDB (Open Movie Database) API. The search system supports title search, type filtering, year filtering, and pagination.

Key Components

  • OmdbService (src/app/shared/services/omdb/omdb.service.ts) - Handles OMDB API requests
  • SearchComponent (src/app/pages/search/page/search.component.ts) - Main search page
  • SearchBarComponent - Search form with filters
  • MovieResultsTableComponent - Displays search results

Search Service

The OmdbService provides methods to interact with the OMDB API:
src/app/shared/services/omdb/omdb.service.ts
import { Injectable } from '@angular/core';
import { Observable} from 'rxjs';
import { HttpClient, HttpParams } from '@angular/common/http';
import { environment } from 'src/environments/environment.development';
import { OmdbResponse } from '../../models/omdbResponse.model';
import { OmdbDetails } from '../../models/ombdDetails';

@Injectable({
  providedIn: 'root'
})
export class OmdbService {

  constructor(private http: HttpClient) { }

  fetchMediaItems(title: string, type: string, year: string, page: number): Observable<OmdbResponse> {
    const options = {
      params: new HttpParams()
        .set('title', title.trim())
        .set('type', type)
        .set('year', year)
        .set('page', page.toString())
    };
    return this.http.get<OmdbResponse>(`${environment.serverSearchURL}`, options)
  }
  
  getMediaItemInfo(imdbId: string): Observable<OmdbDetails> {
    return this.http.get<OmdbDetails>(`${environment.serverSearchURL}/${imdbId}`)
  }
}

Search Parameters

Available Filters

title
string
required
The title of the movie or TV show to search for. Automatically trimmed of whitespace.
type
string
default:"all"
Filter by media type:
  • all - Search all types
  • movie - Movies only
  • series - TV series only
  • episode - Episodes only
year
string
Filter by release year (e.g., “2020”). Leave empty to search all years.
page
number
default:"1"
Page number for pagination. Each page returns up to 10 results.
1

User submits search form

The user enters search criteria in the SearchBarComponent and submits the form:
src/app/pages/search/page/search.component.ts
handleSubmit(filters: SearchFilters): void {
  this.searchState = {
    ...this.searchState,
    ...filters,
    currentPage: 1,
    searchOnProcess: true
  };
  this.fetchMediaItems();
}
2

Call OMDB API through service

The component calls the OmdbService with search parameters:
src/app/pages/search/page/search.component.ts
private fetchMediaItems(): void {
  this.omdbService.fetchMediaItems(
    this.searchState.title,
    this.searchState.type,
    this.searchState.year,
    this.searchState.currentPage)
    .subscribe({
      next: (response) => {
        if (response.Response === "True") {
          this.searchState.collection = response.Search || [];
          this.searchState.collectionSize = Number(response.totalResults) || 0;
          this.focusOnResultsTable()
        } else {
          this.toastrService.warning(response.Error, 'Try again!');
          this.searchState.collection = [];
        }
        this.searchState.searchOnProcess = false;
      },
      error: (error) => {
        this.toastrService.error(error.message);
        this.searchState.searchOnProcess = false;
      }
    })
}
3

Display results

Results are displayed in a table with poster, title, year, and type columns. Users can click on items to view details or add them to favorites.

Search State Management

The SearchComponent maintains search state using a SearchState interface:
src/app/pages/search/page/search.component.ts
searchState: SearchState = {
  title: '',
  type: 'all',
  year: '',
  currentPage: 1,
  pageSize: 10,
  collection: [],
  collectionSize: 0,
  searchOnProcess: false,
};

State Properties

  • title - Current search query
  • type - Selected media type filter
  • year - Selected year filter
  • currentPage - Current pagination page
  • pageSize - Results per page (fixed at 10)
  • collection - Array of search results
  • collectionSize - Total number of results available
  • searchOnProcess - Loading state indicator

Pagination

Handle pagination by updating the current page and re-fetching results:
src/app/pages/search/page/search.component.ts
loadPage(page: number): void {
  this.searchState.currentPage = page;
  this.fetchMediaItems();
}
The OMDB API returns 10 results per page. The total number of results is available in response.totalResults.

Viewing Media Details

Click on a search result to open a detailed view with additional information:
src/app/pages/search/page/search.component.ts
openMediaItem(mediaItem: MediaItem): void {
  this.loadingCard = true;
  this.dialogService
    .openMediaItem(window.innerWidth, mediaItem, false)
    .pipe(finalize(() => (this.loadingCard = false)))
    .subscribe();
}
The dialog fetches detailed information using the IMDB ID:
getMediaItemInfo(imdbId: string): Observable<OmdbDetails> {
  return this.http.get<OmdbDetails>(`${environment.serverSearchURL}/${imdbId}`)
}
Users can add items directly from search results:
src/app/pages/search/page/search.component.ts
addToFavorites(mediaItem: MediaItem) {
  this.authService.isLoggedInObservable().pipe(
    take(1),
    switchMap(loggedIn => {
      if (!loggedIn) {
        this.toastrService.warning('You must be logged in to add movies to your list', 'Error');
        this.router.navigate(['/auth/login']);
        return EMPTY; 
      }
      return this.favoritesService.addToFavorites(mediaItem);
    })
  ).subscribe({
    next: () => this.toastrService.success(mediaItem.title, 'Added to favorites'),
    error: (error) => this.toastrService.warning(error.message)
  });
}
Users must be logged in to add items to favorites. The function checks authentication status before proceeding.
The search page displays featured media items from a predefined constant:
src/app/pages/search/page/search.component.ts
featuredMedia: MediaItem[] = FEATURED_MEDIA;
These are displayed in a carousel component before search results.

API Integration

The OMDB API is accessed through a proxy endpoint configured in the environment:
src/environments/environment.development.ts
export const environment = {
    serverSearchURL : 'http://localhost:9000/api/omdb',
    // ...
};

API Response Format

Search Response:
{
  "Search": [
    {
      "Title": "The Matrix",
      "Year": "1999",
      "imdbID": "tt0133093",
      "Type": "movie",
      "Poster": "https://..."
    }
  ],
  "totalResults": "150",
  "Response": "True"
}
Details Response:
{
  "Title": "The Matrix",
  "Year": "1999",
  "Director": "Lana Wachowski, Lilly Wachowski",
  "Actors": "Keanu Reeves, Laurence Fishburne",
  "Plot": "A computer hacker learns...",
  "imdbRating": "8.7",
  "Poster": "https://...",
  "youtubeURLTrailer": "https://youtube.com/..."
}

Error Handling

When the API returns no results:
if (response.Response === "True") {
  // Handle results
} else {
  this.toastrService.warning(response.Error, 'Try again!');
  this.searchState.collection = [];
}
Common error messages:
  • “Movie not found!” - No results match the search criteria
  • “Too many results” - Search is too broad, add more filters
If the backend server is unreachable:
error: (error) => {
  this.toastrService.error(error.message);
  this.searchState.searchOnProcess = false;
}
The service automatically trims the title and converts parameters to strings:
const options = {
  params: new HttpParams()
    .set('title', title.trim())
    .set('type', type)
    .set('year', year)
    .set('page', page.toString())
};

Search Results Table

The search results are displayed in a table with the following columns:
src/app/pages/search/page/search.component.ts
displayedColumns: string[] = ['title', 'year', 'type', 'poster', 'Add'];
  • Title - Movie or TV show title
  • Year - Release year
  • Type - Media type (movie, series, episode)
  • Poster - Thumbnail image
  • Add - Button to add to favorites

Best Practices

Trim Search Input

Always trim whitespace from search titles to avoid API errors and improve search accuracy.

Handle Loading States

Use searchOnProcess to show loading indicators and prevent duplicate requests.

Check Authentication

Verify users are logged in before allowing them to add items to favorites.

Implement Pagination

Display pagination controls when collectionSize exceeds pageSize to help users navigate results.

Example Usage

// Search for movies with "matrix" in the title
this.omdbService.fetchMediaItems('matrix', 'movie', '', 1)
  .subscribe(response => {
    console.log(response.Search);
  });

Search with Filters

// Search for series from 2020
this.omdbService.fetchMediaItems('breaking', 'series', '2020', 1)
  .subscribe(response => {
    console.log(response.Search);
  });

Get Detailed Information

// Get details for a specific movie
this.omdbService.getMediaItemInfo('tt0133093')
  .subscribe(details => {
    console.log(details.Plot);
    console.log(details.imdbRating);
  });
  • src/app/shared/services/omdb/omdb.service.ts - OMDB API service
  • src/app/pages/search/page/search.component.ts - Search page component
  • src/app/pages/search/components/search-bar/search-bar.component.ts - Search form
  • src/app/pages/search/components/movie-results-table/movie-results-table.component.ts - Results table
  • src/app/pages/search/components/carousel/carousel.component.ts - Featured media carousel
  • src/environments/environment.development.ts - Environment configuration

Build docs developers (and LLMs) love