skip to Main Content

I have been working on an SPA with Angular 16, TypeScript and The Movie Database (TMDB).

I show movies in a list (collection), with each movie displayed in MovieCardComponent component that looks like this:

import { Component, Input } from '@angular/core';
import { Movie } from '../../models/Movie';
import { Genre, GenreResponse } from '../../models/Genre';
import { MovieService } from '../../services/movie-service.service';

@Component({
  selector: 'app-movie-card',
  templateUrl: './movie-card.component.html',
  styleUrls: ['./movie-card.component.scss']
})

export class MovieCardComponent {

  constructor(private movieService: MovieService) {}

  @Input() movie!: Movie;

  public genreResponse!: GenreResponse;
  public genres: Genre[] | undefined = [];
  public movie_genres: Genre[] = [];

  public movieCardImage: string = !this.movie?.backdrop_path
    ? '/assets/images/generic-card-image.png'
    : `https://image.tmdb.org/t/p/w500/${this.movie?.backdrop_path}`;


    public getMovieGenres() {
      this.movieService.getMovieGenres().subscribe((response) => {
        this.genreResponse = response;
        this.genres = this.genreResponse.genres;

        if (this.genres && this.movie.genre_ids.length) {
          this.movie_genres = this.genres.filter((genre: Genre) => this.movie?.genre_ids.includes(genre.id))
        }
      });
    }

    ngOnInit() {
      this.getMovieGenres();
    }
}

The template:

<div class="thumbnail">
  <img [src]="movieCardImage" [alt]="movie.title" class="img-fluid" />
</div>

The goal

Since not all the movies have posters, I want the card to display a default image, unless the movie does have a poster.

For this purpose, I have:

public movieCardImage: string = !this.movie?.backdrop_path
    ? '/assets/images/generic-card-image.png'
    : `https://image.tmdb.org/t/p/w500/${this.movie?.backdrop_path}`;

The problem

The problem is that all cards display the default image, and I know for sure that most do have a poster.

Questions

  1. What am I doing wrong?
  2. What is the most reliable way to fix this issue?

2

Answers


  1. Chosen as BEST ANSWER

    I solved by changing the MovieCardComponent class to this:

    export class MovieCardComponent {
    
      constructor(private movieService: MovieService) { }
    
      @Input() movie!: Movie;
    
      public genreResponse!: GenreResponse;
      public genres: Genre[] | undefined = [];
      public movie_genres: Genre[] = [];
      public movieCardImage: string = '';
    
      public getImage() {
        this.movieCardImage = this.movie?.backdrop_path
          ? `https://image.tmdb.org/t/p/w500/${this.movie?.backdrop_path}`
          : '/assets/images/generic-card-image.png';
      }
    
      public getMovieGenres() {
        this.movieService.getMovieGenres().subscribe((response) => {
          this.genreResponse = response;
          this.genres = this.genreResponse.genres;
    
          if (this.genres && this.movie.genre_ids.length) {
            this.movie_genres = this.genres.filter((genre: Genre) => this.movie?.genre_ids.includes(genre.id))
          }
        });
      }
    
      ngOnInit() {
        this.getMovieGenres();
        this.getImage();
      }
    }
    

  2. The ternary condition needs to be swapped, this will solve your issue, if the image exists, we show it, else we fallback the default image!

    TS

    getImage(): string {
        return this.movie?.backdrop_path
        ? `https://image.tmdb.org/t/p/w500/${this.movie?.backdrop_path}`
        : '/assets/images/generic-card-image.png';
    }
    
    public movieCardImage: string = this.getImage();
    

    html

    <div class="thumbnail">
      <img [src]="movieCardImage" [alt]="movie.title" class="img-fluid" />
    </div>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search